Brendan Miller wrote:
I have a filter with doFilter method like this:

    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain chain)
        throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        resp.setHeader("Cache-Control",
                       "must-revalidate, max-age=0, post-check=0,
pre-check=0");

        chain.doFilter(request, response);
    }

This sets the header. However, if I set the header *after* chain.doFilter,
the header is not set. Why is this?

    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain chain)
        throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        chain.doFilter(request, response);

        resp.setHeader("Cache-Control",
                       "must-revalidate, max-age=0, post-check=0,
pre-check=0");
    }

Programmatically I can see the header is null.

Has the content already been sent to the web browser after chain.doFilter?
If so, is there a way to delay sending data to the browser? I need to
inspect the status code in the response before setting my header (to
prevent 404's from being cached).


Not a direct answer to your question, but this subject comes up so often that maybe a generic explanation may help.

What is the meaning of "the response is already committed" ?

In the HTTP protocol, a HTTP Response consists of :

- a HTTP "status line"  (like : "200 OK")
- 0 or more "response headers" (like "Content-length: 1234)
- a blank line
- the response content (like : a html page, or a jpeg image)

(The last 2 elements are optional, as some responses do not have a content part, by definition)

The above is what a HTTP client (e.g. a browser) will be waiting for, after it has sent a request to a HTTP server (e.g., Tomcat). The client will expect the above "response lines" to arrive to it strictly in the order above. It would not expect for example the HTTP status line to come after a HTTP response header or after the content of the response. That means that the HTTP server will need to ensure that the above response lines are written to the client socket also in the order above.

In the course of processing a request, at some point Tomcat will be setting up a "Response object", which is an internal representation of (and a buffer for) the HTTP response that will at some point be sent to the client.

When a webapp is run, the main thing it will usually be doing is to prepare the response content. In the Response object, the status code and the response headers are also being set gradually, as a kind of side-effect (or explicitly). But for the moment, all of this happens in the Response object, in memory, and nothing has yet been sent to the client.

In other words, at this point the Response is still "uncommitted", and the webapp can still manipulate the response status code and the response headers in the Response object.

However, as soon as the webapp starts outputting the response *content* to the client, and before even the first byte of the response content is effectively sent over the client socket, the server has no choice : in order to preserve the expected order in the HTTP response, it must first send the HTTP status line, then the HTTP headers, then a blank line, then the first byte of the response.

That is when the response is "commmitted" (and the server will now set a flag to that effect in the Response object).

From that point on, it is too late to still modify the HTTP status code or the HTTP response headers, because they are already on their way to the client, and the server cannot "grab them back".

So any attempt at that point by the webapp (filters, servlet, whatever) to modify the status or the headers will be met by a refusal : "can't do that, the response is already committed".




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to