Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] ImageIO in servlet: should I close the httpResp.getOutputStream() and how to set Content-Length?

Inline ...


On Fri, Oct 4, 2019 at 4:05 AM Alexander Farber <alexander.farber@xxxxxxxxx> wrote:
Good morning,

I am using Jetty 9.4.21.v20190926 - as a standalone server behind HAProxy and also I compile my custom WAR servlet against it.

It serves Websockets, GET, POST requests and works very well, thank you!

However now I would like to generate a PNG file using ImageIO and while the code below works for me, I have 2 questions please -

    @Override
    protected void doGet(HttpServletRequest httpReq, HttpServletResponse httpResp) throws ServletException, IOException {
        if ("board1".equals(httpReq.getServletPath()) {
            BufferedImage image = ImageIO.read(getResource("ru/game_board_1.png"));
            httpResp.setStatus(HttpServletResponse.SC_OK);
            httpResp.setContentType("image/png");
            httpResp.setContentLength(12345); // question 1: should I call this or will Jetty add it automatically?
            ImageIO.write(image, "png", httpResp.getOutputStream());
            httpResp.getOutputStream().close();  // question 2: should I close the output stream here or not?
        }
    }

Question 1: Should I explicitly set Content-Length or will Jetty add it automatically for me? And if I have to set it myself, how to deal with the changed size because of gzip compression?

Content-Length is set by you, but only if you want it.
If you don't set it, and the content you are writing exceeds the buffering in the response, then `Transfer-Encoding: chunked` is used.
If the content happens to fit in the response buffer, it will be given a Content-Length header.
Don't worry about gzip compression, it will readjust based on what it knows at the time.
It also does not recompress the entire content THEN start to send, it sends what it can, and if it happens to fit in a single buffer, great! it's got a Content-Length.

Also, GzipHandler will not, by default, compress content with `Content-Type: image/png`, as it excludes all of the known `image/*` mime-types.
You should really keep it like that, as compressing already compressed content isn't a great idea.
 

Question 2: Should I call httpResp.getOutputStream().close() at the end of doGet() or maybe the output stream is still needed to serve other requests because of Keep-Alive?


The individual HttpServletRequest and HttpServletResponse streams are unrelated to the connection.
Get and close them to fit your own needs.
Generally speaking, closing a HttpServletRequest or HttpServletResponse stream is not a requirement, feel free to just stop using them.
The servlet spec will understand what that means.

`Connection: Keep-Alive` is for HTTP/1.0 and is not used in HTTP/1.1, it has no meaning and is pretty much ignored by most HTTP/1.1 layers.
Why?  
Two reasons, "Keep-Alive" is not a token recognized by the HTTP/1.1 spec, and HTTP/1.1 is Connection persistent by default.
In fact, you'd have to use `Connection: close` on HTTP/1.1 to do the opposite (close the connection after this Http exchange).

- Joakim
 

Back to the top