Skip to content

Instantly share code, notes, and snippets.

@Crydust
Last active April 2, 2021 10:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Crydust/7e4e9228cd95febccdc58f0501c1e327 to your computer and use it in GitHub Desktop.
Save Crydust/7e4e9228cd95febccdc58f0501c1e327 to your computer and use it in GitHub Desktop.
HTTPServer post-process filter (written as answer to https://stackoverflow.com/q/14592299/11451)
package spike;
import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.List;
import static java.util.Arrays.asList;
public class App {
private static final String VERY_LONG_TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse at lacinia diam. Donec aliquam risus ut ante consequat venenatis. Mauris tempus nulla vel lorem maximus, sed euismod sapien sollicitudin. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas volutpat sem odio, in eleifend enim finibus nec. Vivamus in velit sapien. Quisque ac mattis lorem. Curabitur at libero nec lectus hendrerit bibendum hendrerit sed dolor. Cras in ex et purus lobortis tempor eget molestie risus. Integer in libero non urna elementum gravida.\n" +
"\n" +
"Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus eu gravida sem. Curabitur interdum risus nibh, interdum tempor est lacinia sed. Interdum et malesuada fames ac ante ipsum primis in faucibus. Vestibulum euismod pretium tristique. Fusce scelerisque vitae urna eget molestie. Nullam ut diam scelerisque, convallis felis vel, luctus velit. Aenean vestibulum tincidunt erat eget tempor. Suspendisse placerat vulputate diam, id facilisis velit varius vel. Sed viverra porttitor urna non suscipit.\n" +
"\n" +
"Suspendisse dictum leo ullamcorper tellus fermentum lacinia. Integer bibendum ultrices elit, ut ultricies lacus aliquam id. Sed iaculis metus eget tortor molestie, ac luctus nulla facilisis. Pellentesque eleifend turpis elit, eget scelerisque arcu porta at. Nulla in tempus ipsum. Cras vel dictum sem. Sed mollis massa et tortor dictum, sed volutpat odio fringilla.\n" +
"\n" +
"Aenean sit amet ex metus. Aliquam erat volutpat. Nunc justo libero, condimentum vel tristique ac, malesuada eu eros. Sed viverra vehicula mi quis egestas. Suspendisse quis consectetur neque. Nulla tortor ipsum, volutpat ut erat non, pretium maximus velit. Etiam finibus volutpat viverra. Integer eget molestie tellus. Cras ut malesuada nisi. In pharetra a sem quis egestas. Nam congue metus sed ultrices dictum. Nullam dignissim lobortis dolor quis fringilla.\n" +
"\n" +
"Sed vestibulum eros ut mauris elementum rutrum. Nunc ullamcorper tortor vel dolor varius, mollis iaculis quam congue. Vestibulum id urna nec mauris fermentum commodo. Vivamus tellus felis, convallis et eros id, viverra semper nisi. Fusce convallis mattis ante. Nulla pulvinar arcu purus, in tincidunt nibh ullamcorper sed. Nullam aliquet consequat arcu, non maximus nulla tincidunt scelerisque. Pellentesque mollis lacinia purus. Aliquam sodales mi id odio maximus faucibus. Sed non enim eu tortor rutrum aliquam in quis justo. Pellentesque ut magna in turpis eleifend bibendum ut a diam. Suspendisse varius, augue vel pharetra egestas, urna enim condimentum tortor, ultrices facilisis dui enim at nibh. Ut in nisl eu magna rutrum maximus.";
public static void main(String[] args) throws IOException, InterruptedException {
HttpServer hs = createServer();
Thread.sleep(60_000L);
hs.stop(0);
}
private static HttpServer createServer() throws IOException {
List<Filter> filters = asList(new GzipFilter());
HttpServer hs = HttpServer.create(new InetSocketAddress("127.0.0.1", 8080), 0);
hs.createContext("/", text(VERY_LONG_TEXT)).getFilters().addAll(filters);
hs.start();
return hs;
}
private static HttpHandler text(String body) {
byte[] bodyBytes = body.getBytes(StandardCharsets.UTF_8);
int responseLength = bodyBytes.length;
return he -> {
try {
he.getResponseHeaders().add("Content-Type", "text/plain; charset=UTF-8");
he.sendResponseHeaders(200, responseLength);
try (OutputStream out = he.getResponseBody()) {
out.write(bodyBytes);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
};
}
}
package spike;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpPrincipal;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URI;
class ForwardingHttpExchange extends HttpExchange {
private final HttpExchange inner;
ForwardingHttpExchange(HttpExchange inner) {
this.inner = inner;
}
@Override
public Headers getRequestHeaders() {
return inner.getRequestHeaders();
}
@Override
public Headers getResponseHeaders() {
return inner.getResponseHeaders();
}
@Override
public URI getRequestURI() {
return inner.getRequestURI();
}
@Override
public String getRequestMethod() {
return inner.getRequestMethod();
}
@Override
public HttpContext getHttpContext() {
return inner.getHttpContext();
}
@Override
public void close() {
inner.close();
}
@Override
public InputStream getRequestBody() {
return inner.getRequestBody();
}
@Override
public OutputStream getResponseBody() {
return inner.getResponseBody();
}
@Override
public void sendResponseHeaders(int rCode, long responseLength) throws IOException {
inner.sendResponseHeaders(rCode, responseLength);
}
@Override
public InetSocketAddress getRemoteAddress() {
return inner.getRemoteAddress();
}
@Override
public int getResponseCode() {
return inner.getResponseCode();
}
@Override
public InetSocketAddress getLocalAddress() {
return inner.getLocalAddress();
}
@Override
public String getProtocol() {
return inner.getProtocol();
}
@Override
public Object getAttribute(String name) {
return inner.getAttribute(name);
}
@Override
public void setAttribute(String name, Object value) {
inner.setAttribute(name, value);
}
@Override
public void setStreams(InputStream i, OutputStream o) {
inner.setStreams(i, o);
}
@Override
public HttpPrincipal getPrincipal() {
return inner.getPrincipal();
}
}
package spike;
import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.regex.Pattern;
import java.util.zip.GZIPOutputStream;
import static java.util.Arrays.asList;
import static java.util.Objects.requireNonNullElse;
final class GzipFilter extends Filter {
private static final Pattern COMMA_PATTERN = Pattern.compile("\\s*,\\s*");
@Override
public void doFilter(HttpExchange exchange, Chain chain) throws IOException {
final String acceptEncoding = exchange.getRequestHeaders().getFirst("Accept-Encoding");
final List<String> acceptEncodings = asList(COMMA_PATTERN.split(requireNonNullElse(acceptEncoding, "")));
chain.doFilter(
acceptEncodings.contains("gzip")
? new GzipHttpExchange(exchange)
: exchange
);
}
@Override
public String description() {
return "GzipFilter";
}
private static class GzipHttpExchange extends ForwardingHttpExchange {
private GZIPOutputStream wrappedResponseBody = null;
GzipHttpExchange(HttpExchange inner) {
super(inner);
}
@Override
public OutputStream getResponseBody() {
return wrappedResponseBody != null
? wrappedResponseBody
: super.getResponseBody();
}
@Override
public void sendResponseHeaders(int rCode, long responseLength) throws IOException {
getResponseHeaders().add("Vary", "Accept-Encoding");
if (responseLength >= 0) {
getResponseHeaders().add("Content-Encoding", "gzip");
super.sendResponseHeaders(rCode, 0);
wrappedResponseBody = new GZIPOutputStream(super.getResponseBody());
return;
}
super.sendResponseHeaders(rCode, responseLength);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment