tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From André Warnier ...@ice-sa.com>
Subject Re: filter question
Date Fri, 14 Mar 2014 12:25:13 GMT
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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message