Discussion:
setHeader after DoFilter delegation in filter?
Michael Larson
2008-10-07 17:13:53 UTC
Permalink
Hello,

I'm debugging a tomcat filter. The filter has been designed as follows:

MyFilter::DoFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
{
do_some_stuff();

//now delegate the call the chain
chain.DoFilter();

//the header value below doesn't always show up at the client
response.setHeader("post-filter","true");
}


For the jsp page being accessed I've turned off AutoFlush (via a server
side directive). However, I'm still seeing this page (if it exceeds a
certain size but well below the jspwriter buffer size) will be sent back
to the client before the response header has been modified.

All the examples I found place the delegation of the chain.DoFilter()
call placed at the very end of the filter.

If AutoFlush is turned off for the jsp page and the page doesn't exceed
the buffer size can it still send the response back to the client before
the filter chain has completed (and in this example before the header
has been modified)? Is it a bad idea to modify the response header after
the call to chain.DoFilter()?

The version of tomcat is v5.5.23, and no exceptions are thrown when the
setHeader call is made.

TIA

Mike

---------------------------------------------------------------------
To start a new topic, e-mail: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
Christopher Schultz
2008-10-07 18:49:00 UTC
Permalink
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Michael,
Post by Michael Larson
MyFilter::DoFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
{
do_some_stuff();
//now delegate the call the chain
chain.DoFilter();
//the header value below doesn't always show up at the client
response.setHeader("post-filter","true");
}
This might not work because the response could have been committed. If
the response buffer is filled, then the headers will be sent back to the
client. If you come along later and try to set a header, you'll get an
exception.
Post by Michael Larson
For the jsp page being accessed I've turned off AutoFlush (via a server
side directive). However, I'm still seeing this page (if it exceeds a
certain size but well below the jspwriter buffer size) will be sent back
to the client before the response header has been modified.
I'm not sure about autoFlush, but it may be that you're hitting a hard
buffer limit and the data is being sent, anyway.
Post by Michael Larson
If AutoFlush is turned off for the jsp page and the page doesn't exceed
the buffer size can it still send the response back to the client before
the filter chain has completed (and in this example before the header
has been modified)? Is it a bad idea to modify the response header after
the call to chain.DoFilter()?
It's much better to do it up front if you can. Why do you need the
header to be set after the fact?

If you really must do this, you can always do your own buffering by
wrapping the request along with your own OutputStream/Writer that
buffers itself.
Post by Michael Larson
The version of tomcat is v5.5.23, and no exceptions are thrown when the
setHeader call is made.
That's interesting that no exceptions are thrown. :(

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkjrrxwACgkQ9CaO5/Lv0PAKdwCfbEXaoIj5cnMLIYZciiEXcAL8
0TMAn0CWqgdA8qQNsZwDabIQHbRHPoqY
=Gqzj
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To start a new topic, e-mail: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
slioch
2008-10-10 05:36:54 UTC
Permalink
Thanks for the response Christopher.

Unfortunately I need to set a value in the header after the doFilter()
delegation. The reason is that header valuedepends on the result of the page
rendering.

So, if autoflush is disabled and the buffer size is not exceeded for the
page shouldn't a setHeader() call made after the doFilter() call be able to
set the value in the response header?

Or, to put it another way, does the j2ee spec (or tomcat design) always
start sending the response to the client when the page is rendered (after
the last filter has been executed in a filter chain), or after the
filterchain has completed its processing?

Mike
Post by Christopher Schultz
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Michael,
Post by Michael Larson
MyFilter::DoFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
{
do_some_stuff();
//now delegate the call the chain
chain.DoFilter();
//the header value below doesn't always show up at the client
response.setHeader("post-filter","true");
}
This might not work because the response could have been committed. If
the response buffer is filled, then the headers will be sent back to the
client. If you come along later and try to set a header, you'll get an
exception.
Post by Michael Larson
For the jsp page being accessed I've turned off AutoFlush (via a server
side directive). However, I'm still seeing this page (if it exceeds a
certain size but well below the jspwriter buffer size) will be sent back
to the client before the response header has been modified.
I'm not sure about autoFlush, but it may be that you're hitting a hard
buffer limit and the data is being sent, anyway.
Post by Michael Larson
If AutoFlush is turned off for the jsp page and the page doesn't exceed
the buffer size can it still send the response back to the client before
the filter chain has completed (and in this example before the header
has been modified)? Is it a bad idea to modify the response header after
the call to chain.DoFilter()?
It's much better to do it up front if you can. Why do you need the
header to be set after the fact?
If you really must do this, you can always do your own buffering by
wrapping the request along with your own OutputStream/Writer that
buffers itself.
Post by Michael Larson
The version of tomcat is v5.5.23, and no exceptions are thrown when the
setHeader call is made.
That's interesting that no exceptions are thrown. :(
- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkjrrxwACgkQ9CaO5/Lv0PAKdwCfbEXaoIj5cnMLIYZciiEXcAL8
0TMAn0CWqgdA8qQNsZwDabIQHbRHPoqY
=Gqzj
-----END PGP SIGNATURE-----
---------------------------------------------------------------------
--
View this message in context: http://www.nabble.com/setHeader-after-DoFilter-delegation-in-filter--tp19862960p19912296.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To start a new topic, e-mail: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
André Warnier
2008-10-10 07:30:28 UTC
Permalink
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: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
Pid
2008-10-10 08:43:57 UTC
Permalink
Post by André Warnier
[...]
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
- 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
Post by André Warnier
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: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
slioch
2008-10-10 20:44:02 UTC
Permalink
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).

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
Post by Pid
Post by André Warnier
[...]
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
- 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,
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
Post by André Warnier
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".
---------------------------------------------------------------------
---------------------------------------------------------------------
--
View this message in context: http://www.nabble.com/setHeader-after-DoFilter-delegation-in-filter--tp19862960p19925786.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To start a new topic, e-mail: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
André Warnier
2008-10-10 21:09:11 UTC
Permalink
Post by slioch
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.
Post by slioch
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
Post by Pid
Post by André Warnier
[...]
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
- 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,
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
Post by André Warnier
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: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
Caldarale, Charles R
2008-10-10 21:27:02 UTC
Permalink
Subject: Re: setHeader after DoFilter delegation in filter?
To create output for the client, the application calls
something, right? (I mean a method of HttpRequest).
Not quite - you're confusing request with response. There are methods in HttpServletResponse - an Interface, not a class - to obtain a PrintWriter or ServletOutputStream that the webapp uses to generate data to be sent to the client at some point in the future. The data isn't sent until flushBuffer(), sendError(), or sendRedirect() are called. Since the HttpServletResponseWrapper class implements the interface, those methods are available via the wrapper. The filter needs to subclass the wrapper in order to subvert anything else in the filter/servlet chain.

- Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.

---------------------------------------------------------------------
To start a new topic, e-mail: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
slioch
2008-10-11 03:59:33 UTC
Permalink
Sorry all--I'm still stumped. Tried the suggestions and here's what I found.

I've subclass HttpServletResponseWrapper and overloaded the following
methods:

public void flushBuffer();
public void sendRedirect(String str);
public void sendError(int sc);
public void sendError(int sc, String msg);

in my new response wrapper. These methods have been disabled while
processing is in the scope of my filter (I also record if these methods are
called). I've replaced the response object with my new wrapper:

public void doFilter(ServletRequest req, ServletResponse res,
FilterChain fc)
throws java.io.IOException, javax.servlet.ServletException {
ResponseWrapper resp = new ResponseWrapper((HttpServletResponse)(res));


And I've found that sendError(), sendRedirect(), and flushBuffer() are not
being called while in the processing is in the scope of my filter. In other
words the filter looks something like:

dofilter(ServletRequest req, ServletResponse res, FilterChain fc)
{
ResponseWrapper resp = new ResponseWrapper((HttpServletResponse)(res));
//resp.isCommitted() returns false
//some processing work
//resp.isCommitted() returns false;
fc.doFilter(req,resp);
//resp.isCommitted() returns TRUE
//some more process work
return;
}

If I know that sendError(), sendRedirect(), and flushBuffer() are not being
called how would response be sent (provided autoflush is false and the
buffer size is large enough for the print writer). Thanks for the help (and
patience)!

mike
Post by Caldarale, Charles R
Subject: Re: setHeader after DoFilter delegation in filter?
To create output for the client, the application calls
something, right? (I mean a method of HttpRequest).
Not quite - you're confusing request with response. There are methods in
HttpServletResponse - an Interface, not a class - to obtain a PrintWriter
or ServletOutputStream that the webapp uses to generate data to be sent to
the client at some point in the future. The data isn't sent until
flushBuffer(), sendError(), or sendRedirect() are called. Since the
HttpServletResponseWrapper class implements the interface, those methods
are available via the wrapper. The filter needs to subclass the wrapper
in order to subvert anything else in the filter/servlet chain.
- Chuck
THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY
MATERIAL and is thus for use only by the intended recipient. If you
received this in error, please contact the sender and delete the e-mail
and its attachments from all computers.
---------------------------------------------------------------------
--
View this message in context: http://www.nabble.com/setHeader-after-DoFilter-delegation-in-filter--tp19862960p19929361.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To start a new topic, e-mail: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
André Warnier
2008-10-11 09:47:04 UTC
Permalink
Hi.
I found an approximative example for you, here :
http://www.javafaq.nu/java-example-code-237.html
(searching Google for "HttpServletResponseWrapper example"

If I remember well, what you want to achieve is : depending on the
response content that the webapp generates, you would like to set a
response header. This response header has to be set of course, before
the first byte of output content is sent to the browser.

Before your webapp is going to send this first byte, it will need to get
some form of output stream to write the byte to.
It will do that using one of the methods available to webapps to get
such an output stream, which I identify as either getOutputStream or
getWriter.
So what you probably need to do in your wrapper, is to override these
two methods, so that when the servlet calls one of them, you can return
your own version of it instead of the regular one.
In this way, later your wrapper can "sit in the middle" when the webapp
starts writing to its output, and you can examine this output before
forwarding it to the "real" servlet output stream. Of course before you
forward the output there, you will have determined which header you want
to add and sent it out.

Not very easy, and over my current capacities.
Unfortunately the example I provided above is a bit of a cheat, because
all it has to do is replace the original stream by a compressed one, for
which there is apparently already a convenient class available.

One of the important elements maybe, is how much of the output you need
to see in order to determine which header to add.
If it is just the first few bytes, then I suppose you could buffer this
in memory until you have enough, send out your header, and then set a
flag so that subsequent servlet writes happen as transparently as possible.
If it is the whole response and it can be big, then you might have to
buffer the entire response to disk before setting your header, and then
re-read the original response and sending it out yourself.
Post by slioch
Sorry all--I'm still stumped. Tried the suggestions and here's what I found.
I've subclass HttpServletResponseWrapper and overloaded the following
public void flushBuffer();
public void sendRedirect(String str);
public void sendError(int sc);
public void sendError(int sc, String msg);
in my new response wrapper. These methods have been disabled while
processing is in the scope of my filter (I also record if these methods are
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain fc)
throws java.io.IOException, javax.servlet.ServletException {
ResponseWrapper resp = new ResponseWrapper((HttpServletResponse)(res));
And I've found that sendError(), sendRedirect(), and flushBuffer() are not
being called while in the processing is in the scope of my filter. In other
dofilter(ServletRequest req, ServletResponse res, FilterChain fc)
{
ResponseWrapper resp = new ResponseWrapper((HttpServletResponse)(res));
//resp.isCommitted() returns false
//some processing work
//resp.isCommitted() returns false;
fc.doFilter(req,resp);
//resp.isCommitted() returns TRUE
//some more process work
return;
}
If I know that sendError(), sendRedirect(), and flushBuffer() are not being
called how would response be sent (provided autoflush is false and the
buffer size is large enough for the print writer). Thanks for the help (and
patience)!
mike
Post by Caldarale, Charles R
Subject: Re: setHeader after DoFilter delegation in filter?
To create output for the client, the application calls
something, right? (I mean a method of HttpRequest).
Not quite - you're confusing request with response. There are methods in
HttpServletResponse - an Interface, not a class - to obtain a PrintWriter
or ServletOutputStream that the webapp uses to generate data to be sent to
the client at some point in the future. The data isn't sent until
flushBuffer(), sendError(), or sendRedirect() are called. Since the
HttpServletResponseWrapper class implements the interface, those methods
are available via the wrapper. The filter needs to subclass the wrapper
in order to subvert anything else in the filter/servlet chain.
- Chuck
THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY
MATERIAL and is thus for use only by the intended recipient. If you
received this in error, please contact the sender and delete the e-mail
and its attachments from all computers.
---------------------------------------------------------------------
---------------------------------------------------------------------
To start a new topic, e-mail: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
Pid
2008-10-11 10:44:54 UTC
Permalink
Post by André Warnier
Hi.
http://www.javafaq.nu/java-example-code-237.html
(searching Google for "HttpServletResponseWrapper example"
If I remember well, what you want to achieve is : depending on the
response content that the webapp generates, you would like to set a
response header. This response header has to be set of course, before
the first byte of output content is sent to the browser.
Before your webapp is going to send this first byte, it will need to get
some form of output stream to write the byte to.
It will do that using one of the methods available to webapps to get
such an output stream, which I identify as either getOutputStream or
getWriter.
I suspect it will rather depend on the type of processing the OP is
trying to do on the output, maybe he can enlighten us?
Post by André Warnier
So what you probably need to do in your wrapper, is to override these
two methods, so that when the servlet calls one of them, you can return
your own version of it instead of the regular one.
In this way, later your wrapper can "sit in the middle" when the webapp
starts writing to its output, and you can examine this output before
forwarding it to the "real" servlet output stream. Of course before you
forward the output there, you will have determined which header you want
to add and sent it out.
Andre is making the point that the processing could be done inside the
wrapper, rather than in the filter - which is only there to allow you to
wrap the response.
Post by André Warnier
Not very easy, and over my current capacities.
As above, depends on the type of processing required... the use of a
ByteArrayOutputStream may be a simple way of buffering the response for
example.

p
Post by André Warnier
Unfortunately the example I provided above is a bit of a cheat, because
all it has to do is replace the original stream by a compressed one, for
which there is apparently already a convenient class available.
One of the important elements maybe, is how much of the output you need
to see in order to determine which header to add.
If it is just the first few bytes, then I suppose you could buffer this
in memory until you have enough, send out your header, and then set a
flag so that subsequent servlet writes happen as transparently as possible.
If it is the whole response and it can be big, then you might have to
buffer the entire response to disk before setting your header, and then
re-read the original response and sending it out yourself.
Post by slioch
Sorry all--I'm still stumped. Tried the suggestions and here's what I found.
I've subclass HttpServletResponseWrapper and overloaded the following
public void flushBuffer();
public void sendRedirect(String str);
public void sendError(int sc);
public void sendError(int sc, String msg);
in my new response wrapper. These methods have been disabled while
processing is in the scope of my filter (I also record if these methods are
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain fc)
throws java.io.IOException, javax.servlet.ServletException {
ResponseWrapper resp = new
ResponseWrapper((HttpServletResponse)(res));
And I've found that sendError(), sendRedirect(), and flushBuffer() are not
being called while in the processing is in the scope of my filter. In other
dofilter(ServletRequest req, ServletResponse res, FilterChain fc)
{
ResponseWrapper resp = new
ResponseWrapper((HttpServletResponse)(res));
//resp.isCommitted() returns false
//some processing work
//resp.isCommitted() returns false;
fc.doFilter(req,resp);
//resp.isCommitted() returns TRUE
//some more process work
return;
}
If I know that sendError(), sendRedirect(), and flushBuffer() are not being
called how would response be sent (provided autoflush is false and the
buffer size is large enough for the print writer). Thanks for the help (and
patience)!
mike
Post by Caldarale, Charles R
Subject: Re: setHeader after DoFilter delegation in filter?
To create output for the client, the application calls
something, right? (I mean a method of HttpRequest).
Not quite - you're confusing request with response. There are methods in
HttpServletResponse - an Interface, not a class - to obtain a PrintWriter
or ServletOutputStream that the webapp uses to generate data to be sent to
the client at some point in the future. The data isn't sent until
flushBuffer(), sendError(), or sendRedirect() are called. Since the
HttpServletResponseWrapper class implements the interface, those methods
are available via the wrapper. The filter needs to subclass the wrapper
in order to subvert anything else in the filter/servlet chain.
- Chuck
THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY
MATERIAL and is thus for use only by the intended recipient. If you
received this in error, please contact the sender and delete the e-mail
and its attachments from all computers.
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
To start a new topic, e-mail: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
slioch
2008-10-17 00:43:41 UTC
Permalink
Thanks for the responses. The reason we need to look at the response before
setting a header value is to support a dynamic caching behavior, where the
caching determination is made after examining the response and what database
interactions are made as a result of building the response.

So, I took your advice and implemented a responsewrapper object. This worked
in buffering the response, however a new problem cropped up. I think it's
mine--but I found out that I need to also buffer the header values and
commit these to the response as well. Still looking at my source though.

Thanks all!
Post by Pid
Post by André Warnier
Hi.
http://www.javafaq.nu/java-example-code-237.html
(searching Google for "HttpServletResponseWrapper example"
If I remember well, what you want to achieve is : depending on the
response content that the webapp generates, you would like to set a
response header. This response header has to be set of course, before
the first byte of output content is sent to the browser.
Before your webapp is going to send this first byte, it will need to get
some form of output stream to write the byte to.
It will do that using one of the methods available to webapps to get
such an output stream, which I identify as either getOutputStream or
getWriter.
I suspect it will rather depend on the type of processing the OP is
trying to do on the output, maybe he can enlighten us?
Post by André Warnier
So what you probably need to do in your wrapper, is to override these
two methods, so that when the servlet calls one of them, you can return
your own version of it instead of the regular one.
In this way, later your wrapper can "sit in the middle" when the webapp
starts writing to its output, and you can examine this output before
forwarding it to the "real" servlet output stream. Of course before you
forward the output there, you will have determined which header you want
to add and sent it out.
Andre is making the point that the processing could be done inside the
wrapper, rather than in the filter - which is only there to allow you to
wrap the response.
Post by André Warnier
Not very easy, and over my current capacities.
As above, depends on the type of processing required... the use of a
ByteArrayOutputStream may be a simple way of buffering the response for
example.
p
Post by André Warnier
Unfortunately the example I provided above is a bit of a cheat, because
all it has to do is replace the original stream by a compressed one, for
which there is apparently already a convenient class available.
One of the important elements maybe, is how much of the output you need
to see in order to determine which header to add.
If it is just the first few bytes, then I suppose you could buffer this
in memory until you have enough, send out your header, and then set a
flag so that subsequent servlet writes happen as transparently as possible.
If it is the whole response and it can be big, then you might have to
buffer the entire response to disk before setting your header, and then
re-read the original response and sending it out yourself.
Post by slioch
Sorry all--I'm still stumped. Tried the suggestions and here's what I found.
I've subclass HttpServletResponseWrapper and overloaded the following
public void flushBuffer();
public void sendRedirect(String str);
public void sendError(int sc);
public void sendError(int sc, String msg);
in my new response wrapper. These methods have been disabled while
processing is in the scope of my filter (I also record if these methods are
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain fc)
throws java.io.IOException, javax.servlet.ServletException {
ResponseWrapper resp = new
ResponseWrapper((HttpServletResponse)(res));
And I've found that sendError(), sendRedirect(), and flushBuffer() are not
being called while in the processing is in the scope of my filter. In other
dofilter(ServletRequest req, ServletResponse res, FilterChain fc)
{
ResponseWrapper resp = new
ResponseWrapper((HttpServletResponse)(res));
//resp.isCommitted() returns false
//some processing work
//resp.isCommitted() returns false;
fc.doFilter(req,resp);
//resp.isCommitted() returns TRUE
//some more process work
return;
}
If I know that sendError(), sendRedirect(), and flushBuffer() are not being
called how would response be sent (provided autoflush is false and the
buffer size is large enough for the print writer). Thanks for the help (and
patience)!
mike
Post by Caldarale, Charles R
Subject: Re: setHeader after DoFilter delegation in filter?
To create output for the client, the application calls
something, right? (I mean a method of HttpRequest).
Not quite - you're confusing request with response. There are methods in
HttpServletResponse - an Interface, not a class - to obtain a PrintWriter
or ServletOutputStream that the webapp uses to generate data to be sent to
the client at some point in the future. The data isn't sent until
flushBuffer(), sendError(), or sendRedirect() are called. Since the
HttpServletResponseWrapper class implements the interface, those methods
are available via the wrapper. The filter needs to subclass the wrapper
in order to subvert anything else in the filter/servlet chain.
- Chuck
THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY
MATERIAL and is thus for use only by the intended recipient. If you
received this in error, please contact the sender and delete the e-mail
and its attachments from all computers.
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
--
View this message in context: http://www.nabble.com/setHeader-after-DoFilter-delegation-in-filter--tp19862960p20024120.html
Sent from the Tomcat - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To start a new topic, e-mail: ***@tomcat.apache.org
To unsubscribe, e-mail: users-***@tomcat.apache.org
For additional commands, e-mail: users-***@tomcat.apache.org
Loading...