tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From André Warnier>
Subject Re: setHeader after DoFilter delegation in filter?
Date Fri, 10 Oct 2008 07:30:28 GMT
slioch wrote:
I'll risk an explanation here..

I think maybe the issue is a misunderstanding of how a servlet filter 
works.  It took me a while too, but I think I've got it in the end.
Sorry if this is level 101, that's my own level.

What was confusing to me at first, is that this is different from, for 
instance, Apache input and output filters.  There there is a clear 
distinction between an input filter, which sees all the data on the way 
in to the application, and an output filter, which sees all the data 
that the application produces, before it goes out to the browser.  An 
input filter and and output filter are two separate pieces of code, and 
you can install them independently.

In the Java servlet view of things, a filter is a "wrapper", within 
which the other filters and the webapp run.
It's like an onion : your filter is the outer layer, within which there 
are possibly further layers (other filters), and at the center is the 
webapp.  When your filter calls doFilter(), it executes all its inner 
layers in one go.  The bummer is that, unless you take pains to change 
that, each of these layers has a direct access to the output buffers, 
which live outside the onion. So unless you prevent them from doing 
that, they will start putting bytes there, and by the time your 
doFilter() returns, it's too late to change that.

When you execute doFilter(), in fact you execute, at that point, all the 
further filters that are in the chain, and the webapp at the deepest 
level.  If any of these starts sending output, then by the time the 
doFilter() returns, that output is already "past" your filter, and there 
is nothing you can do anymore to modify it.

If you want something else to happen, then you have to do something like 
this :
- in your filter, subclass the HttpRequest, say as "myHttpRequest".  In 
this subclass, redefine the methods that the underlying filters and 
webapp will (presumably) use to send output to the buffer.  In these 
redefined methods, you can then do whatever you want to transform what 
the application sends out via these methods.
- then, instead of passing the original HttpRequest to the doFilter(), 
pass your own myHttpRequest instance of it.

This way, whenever the application "thinks" it is just using the (say) 
HttpRequest.setHeader() method, it is in fact using *your* 
myHttpRequest.setHeader() method, in which you can catch and "pervert" 
whatever you want, before passing it on to the "real" 
HttpRequest.setHeader() method.

The point is, if you let any underlying (from the point of your filter) 
other filter or webapp call i.e. the original setHeader(), then that's 
it : that line of output is now already in the HTTP output buffer queue, 
and by the time your doFilter() returns, it no longer can "claw it back".

To start a new topic, e-mail:
To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message