ImageIO in servlet: should I close the httpResp.getOutputStream() and how to set Content-Length?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

ImageIO in servlet: should I close the httpResp.getOutputStream() and how to set Content-Length?

Alexander Farber
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?

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?

Thank you
Alex

PS: Below is my very simple config file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
    "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Set name="contextPath">/ws</Set>
    <Set name="war"><SystemProperty name="jetty.base"/>/../WebSockets/target/ws-servlet-0.1-SNAPSHOT.war</Set>
</Configure>


_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ImageIO in servlet: should I close the httpResp.getOutputStream() and how to set Content-Length?

Bill Ross-2

It looks like you're reading the whole png before sending, where you could save latency and memory for big files and have a good general method by using the static resource servlet given here:

http://stackoverflow.com/questions/132052/servlet-for-serving-static-content

Bill

On 10/4/19 2:04 AM, Alexander Farber 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?

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?

Thank you
Alex

PS: Below is my very simple config file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
    "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Set name="contextPath">/ws</Set>
    <Set name="war"><SystemProperty name="jetty.base"/>/../WebSockets/target/ws-servlet-0.1-SNAPSHOT.war</Set>
</Configure>


_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ImageIO in servlet: should I close the httpResp.getOutputStream() and how to set Content-Length?

Bill Ross-2

Plus you'd just be serving raw bytes, which saves time parsing the image format and reconstituting compressed pngs or jpegs for example. It's what I have here:

http://phobrain.com/pr/home/view.html

Bill

On 10/4/19 6:49 AM, Bill Ross wrote:

It looks like you're reading the whole png before sending, where you could save latency and memory for big files and have a good general method by using the static resource servlet given here:

http://stackoverflow.com/questions/132052/servlet-for-serving-static-content

Bill

On 10/4/19 2:04 AM, Alexander Farber 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?

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?

Thank you
Alex

PS: Below is my very simple config file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
    "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Set name="contextPath">/ws</Set>
    <Set name="war"><SystemProperty name="jetty.base"/>/../WebSockets/target/ws-servlet-0.1-SNAPSHOT.war</Set>
</Configure>


_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ImageIO in servlet: should I close the httpResp.getOutputStream() and how to set Content-Length?

Alexander Farber
Hi Bill,

no - I have just listed only a part of my real program which scales, composes several PNGs to one and also adds shapes and texts to it.

So I still wonder: 

1. How to set Content-Length (despite gzip encoding)?
2. And if I should close the output stream or not (won't that break Keep-Alive)?

I have also asked my question at https://stackoverflow.com/q/58234226/165071

Thank you
Alex




_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ImageIO in servlet: should I close the httpResp.getOutputStream() and how to set Content-Length?

Joakim Erdfelt-8
In reply to this post by Alexander Farber
Inline ...


On Fri, Oct 4, 2019 at 4:05 AM Alexander Farber <[hidden email]> 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
 

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: ImageIO in servlet: should I close the httpResp.getOutputStream() and how to set Content-Length?

Alexander Farber
Thank you, Joakim!

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users