package org.caudexorigo.http.netty4;
import io.netty.buffer.ByteBufInputStream;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.caudexorigo.http.netty4.reporting.MessageBody;
import org.caudexorigo.io.UnsynchronizedByteArrayOutputStream;
public class CompressionAdapter extends HttpAction
{
private static final String GZIP_ENCODING = "gzip";
private static final String DEFLATE_ENCODING = "deflate";
private HttpAction wrapped;
public CompressionAdapter(HttpAction wrapped)
{
this.wrapped = wrapped;
}
@Override
public void service(ChannelHandlerContext ctx, FullHttpRequest request, FullHttpResponse response)
{
wrapped.service(ctx, request, response);
int status_code = response.getStatus().code();
boolean allows_body = MessageBody.allow(status_code);
if (!allows_body)
{
return;
}
String accept_enconding = request.headers().get(HttpHeaders.Names.ACCEPT_ENCODING);
boolean allows_gzip = StringUtils.containsIgnoreCase(accept_enconding, GZIP_ENCODING);
boolean allows_deflate = StringUtils.containsIgnoreCase(accept_enconding, DEFLATE_ENCODING);
boolean client_allows_compression = allows_gzip || allows_deflate;
if (client_allows_compression)
{
try
{
UnsynchronizedByteArrayOutputStream bout = new UnsynchronizedByteArrayOutputStream();
ByteBufInputStream uncompressed_response_stream = new ByteBufInputStream(response.content());
if (allows_gzip)
{
response.headers().set(HttpHeaders.Names.CONTENT_ENCODING, GZIP_ENCODING);
copy(uncompressed_response_stream, new GZIPOutputStream(bout, true));
}
else if (allows_deflate)
{
response.headers().set(HttpHeaders.Names.CONTENT_ENCODING, DEFLATE_ENCODING);
copy(uncompressed_response_stream, new DeflaterOutputStream(bout, true));
}
response.content().clear();
response.content().writeBytes(bout.toByteArray());
}
catch (Throwable t)
{
throw new RuntimeException(t);
}
}
}
private static void copy(InputStream input, OutputStream output) throws IOException
{
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1)
{
output.write(buffer, 0, bytesRead);
}
input.close();
output.close();
}
}