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 21:09:11 GMT
slioch wrote:
> Thanks much for the responses. I understand.
> It makes sense to use HttpServletRequestWrapper, but there are no methods in
> HttpServletRequestWrapper or HttpServletRequest that initiates the sending
> of the response back to the client. So, by subclassing HttpServletRequest
> there doesn't appear to be any way to suppress the sending on the response
> back to the client (until I've completed processing).

Yes there is.
To create output for the client, the application calls something, right 
? (I mean a method of HttpRequest).
So, redefine this same method in your subclass.
Then, whenever the application calls this method, thinking it is sending 
output to the client, in fact it calls your method in your subclass.
Sneaky, he ?
Now your method in your subclas gets whatever the webapp thought it was 
sending directly out.
Now it's up to your method, whatever it does with that data, before 
itself calling the real Httprequest method to really send the data out.
For example, you could buffer all the data somewhere waiting for the 
webapp to have finished its complete response.

The above all happens *during* your call to doFilter(), because it is 
during that call that the webapp executes.  The webapp just "calls back" 
into the methods you have defined in your wrapper.
*Then* when your doFilter() returns (meaning the webapp is done), all 
the data is in the buffer, and you start processing it and outputting 
whatever you want.
(Maybe not recommended for megabytes of data, that, but I am sure you'll 
think of something.)

Me speak in mine not really Java-like approximative language, but hope 
you understand what me means.

> What I would like to do is to prevent the response from being sent back to
> the client until my filter has completed it's processing (and this is after
> my filter delegates the doFilter() call to the other filters).
> Mike
> Pid-2 wrote:
>> André Warnier wrote:
>>> 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.
>> Close enough; the spec has some stuff that covers this type of problem,
>> so I'd recommend investigating:
>>  javax.servlet.http.HttpServletRequestWrapper
>>  javax.servlet.http.HttpServletResponseWrapper (hereafter HSRsW)
>> Using the latter should allow you to modify the appropriate header.
>>  HSRsW wrappedHres = new HttpServletResponseWrapper(hres);
>>  chain.doFilter(hreq, wrappedHres);
>> Where your HSRsW contains appropriate code to modify the header, perhaps
>> in the construction phase.
>> p
>>> 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:
>> ---------------------------------------------------------------------
>> To start a new topic, e-mail:
>> To unsubscribe, e-mail:
>> For additional commands, e-mail:

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

View raw message