spring-mvcgziphttpresponsegzipstreamgzipoutputstream

How to do GZIP compression while writing directly to response


I am trying to compress my response when the request header contains gzip in Accept-Encoding. However, adding following to app.properties only works when controller method is returning an object.

server.compression.enabled=true
server.compression.min-response-size=1
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css

I am writing directly to response stream. So, above compression properties don't work.

My method looks like this:

@GetMapping(path = "/something", produces = MediaType.TEXT_PLAIN_VALUE)
public void getSomething(@RequestParam(name = "paramA") String paramA,
                            HttpServletRequest request,
                                  HttpServletResponse response) throws IOException {
            PrintWriter writer = null;
    if (request.getHeader("Accept-Encoding").contains("gzip")) {
        writer = new PrintWriter(new OutputStreamWriter(new GZIPOutputStream(response.getOutputStream())));
        response.addHeader(HttpHeaders.CONTENT_ENCODING, "gzip");
    } else {
        writer = response.getWriter();
    }

    final PrintWriter fwriter = writer;
    someObjectInstance.getSomething(paramA).forEach(x -> {
        fwriter.write(x.toString());
    });
    fwriter.flush();
}

When I curl the above method, I get an empty file. I did try to use the GzipFilter by referring to the following link. http://www.javablog.fr/javaweb-gzip-compression-protocol-http-filter-gzipresponsewrapper-gzipresponsewrapper.html, which works by the way. However, the filter requires alot of boilerplate code. Is there a way I can make changes in controller method and solve the problem as in the link mentioned above.


Solution

  • Just realised I was not closing the writer. After adding fwriter.close(); in the end, the problem was solved.