neo4j Unmanaged Extension: Creating gzipped streamed responses with Jetty
I recently wrote a blog post describing how we created a streamed response and the next thing we wanted to do was gzip the response to shrink it’s size a bit.
A bit of searching led to GZIPContentEncodingFilter popping up a lot of times but this is actually needed for a client processing a gripped response rather than helping us to gzip a response from the server.
I noticed that there was a question about this on the mailing list from about a year ago although Michael pointed out that the repository has now moved and the example is available here instead.
I adapted the example a bit and ended up with the following lifecycle plugin:
package com.markandjim;
public class GZipInitialiser implements SPIPluginLifecycle {
private WebServer webServer;
@Override
public Collection<Injectable<?>> start(NeoServer neoServer) {
webServer = getWebServer(neoServer);
GzipFilter filter = new GzipFilter();
webServer.addFilter(filter, "/*");
return Collections.emptyList();
}
private WebServer getWebServer(final NeoServer neoServer) {
if (neoServer instanceof AbstractNeoServer) {
return ((AbstractNeoServer) neoServer).getWebServer();
}
throw new IllegalArgumentException("expected AbstractNeoServer");
}
@Override
public Collection<Injectable<?>> start(GraphDatabaseService graphDatabaseService, Configuration configuration) {
throw new IllegalAccessError();
}
@Override
public void stop() {
}
}
I then added the following line to 'resources/META-INF/services/org.neo4j.server.plugins.PluginLifecycle:
com.markandjim.GZipInitialiser
After compiling that and deploying the JAR to the 'plugins' I tried calling the end point using cURL:
$ curl -H "Accept-Encoding:gzip,deflate" -v http://localhost:7474/unmanaged/subgraph/1000/1
* About to connect() to localhost port 7474 (#0)
* Trying ::1...
* Connection refused
* Trying 127.0.0.1...
* connected
* Connected to localhost (127.0.0.1) port 7474 (#0)
> GET /unmanaged/subgraph/1000/1 HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: localhost:7474
> Accept: */*
> Accept-Encoding:gzip,deflate
>
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Access-Control-Allow-Origin: *
< Content-Encoding: gzip
< Transfer-Encoding: chunked
< Server: Jetty(6.1.25)
---
gibberish!
The GZIPContentEncodingFilter that I mentioned earlier comes in handy if we want to call the end point from a Jersey client:
public class Neo4jJerseyClient {
public static void main(String[] args) {
Client client = Client.create();
client.addFilter(new GZIPContentEncodingFilter(false));
WebResource webResource = client.resource("http://localhost:7474/unmanaged/subgraph/1000/1");
ClientResponse response = webResource.header("accept-encoding", "gzip,deflate").get(ClientResponse.class);
System.out.println("response = " + response.getEntity(String.class));
}
}
We could also call it using HTTParty from the land of Ruby:
response = HTTParty.get("http://localhost:7474/unmanaged/subgraph/1000/1",
:headers => { 'Accept-Encoding' => 'gzip,deflate' } )
p response
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.