forked from I2P_Developers/i2p.i2p
* I2PTunnelHTTPServer: Don't compress small responses or images
This commit is contained in:
@ -46,6 +46,9 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
private final byte _buf1[];
|
||||
protected boolean _gzip;
|
||||
private long _dataWritten;
|
||||
protected long _dataExpected;
|
||||
protected String _contentType;
|
||||
|
||||
private static final int CACHE_SIZE = 8*1024;
|
||||
private static final ByteCache _cache = ByteCache.getInstance(8, CACHE_SIZE);
|
||||
// OOM DOS prevention
|
||||
@ -130,10 +133,11 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tweak that first HTTP response line (HTTP 200 OK, etc)
|
||||
* Possibly tweak that first HTTP response line (HTTP/1.0 200 OK, etc).
|
||||
* Overridden on server side.
|
||||
*
|
||||
*/
|
||||
protected static String filterResponseLine(String line) {
|
||||
protected String filterResponseLine(String line) {
|
||||
return line;
|
||||
}
|
||||
|
||||
@ -184,6 +188,15 @@ class HTTPResponseOutputStream extends FilterOutputStream {
|
||||
} else if ("Proxy-Authenticate".equalsIgnoreCase(key)) {
|
||||
// filter this hop-by-hop header; outproxy authentication must be configured in I2PTunnelHTTPClient
|
||||
} else {
|
||||
if ("Content-Length".equalsIgnoreCase(key)) {
|
||||
// save for compress decision on server side
|
||||
try {
|
||||
_dataExpected = Long.parseLong(val);
|
||||
} catch (NumberFormatException nfe) {}
|
||||
} else if ("Content-Type".equalsIgnoreCase(key)) {
|
||||
// save for compress decision on server side
|
||||
_contentType = val;
|
||||
}
|
||||
out.write((key.trim() + ": " + val.trim() + "\r\n").getBytes());
|
||||
}
|
||||
break;
|
||||
|
@ -303,18 +303,47 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This plus a typ. HTTP response header will fit into a 1730-byte streaming message.
|
||||
*/
|
||||
private static final int MIN_TO_COMPRESS = 1300;
|
||||
|
||||
private static class CompressedResponseOutputStream extends HTTPResponseOutputStream {
|
||||
private InternalGZIPOutputStream _gzipOut;
|
||||
|
||||
public CompressedResponseOutputStream(OutputStream o) {
|
||||
super(o);
|
||||
_dataExpected = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden to peek at response code. Always returns line.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldCompress() { return true; }
|
||||
protected String filterResponseLine(String line) {
|
||||
String[] s = line.split(" ", 3);
|
||||
if (s.length > 1 &&
|
||||
(s[1].startsWith("3") || s[1].startsWith("5")))
|
||||
_dataExpected = 0;
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't compress small responses or images.
|
||||
* Compression is inline but decompression on the client side
|
||||
* creates a new thread.
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldCompress() {
|
||||
return (_dataExpected < 0 || _dataExpected >= MIN_TO_COMPRESS) &&
|
||||
(_contentType == null || !_contentType.startsWith("image/"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finishHeaders() throws IOException {
|
||||
//if (_log.shouldLog(Log.INFO))
|
||||
// _log.info("Including x-i2p-gzip as the content encoding in the response");
|
||||
if (shouldCompress())
|
||||
out.write("Content-encoding: x-i2p-gzip\r\n".getBytes());
|
||||
super.finishHeaders();
|
||||
}
|
||||
@ -324,9 +353,12 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
//if (_log.shouldLog(Log.INFO))
|
||||
// _log.info("Beginning compression processing");
|
||||
//out.flush();
|
||||
if (shouldCompress()) {
|
||||
_gzipOut = new InternalGZIPOutputStream(out);
|
||||
out = _gzipOut;
|
||||
}
|
||||
}
|
||||
|
||||
public long getTotalRead() {
|
||||
InternalGZIPOutputStream gzipOut = _gzipOut;
|
||||
if (gzipOut != null)
|
||||
@ -334,6 +366,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
public long getTotalCompressed() {
|
||||
InternalGZIPOutputStream gzipOut = _gzipOut;
|
||||
if (gzipOut != null)
|
||||
|
Reference in New Issue
Block a user