tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From André Warnier ...@ice-sa.com>
Subject Re: How to programmatically add parameters to ServletRequest objects?
Date Fri, 08 Aug 2008 09:15:39 GMT
Jonathan,

I am a real beginner at Java and Tomcat, and not so good at it.
But maybe that causes my explanation below to be useful.

The hardest thing for me to understand when I wrote my first servlet 
filter, was that the HttpRequest object that you receive in the filter, 
is not modifiable. In other words, you cannnot just take it, and add a 
HTTP header or a parameter to it, before you pass it on to something 
else.  Like you, I was looking in vain for methods allowing to do that.

What you need to do is "wrap" the original HttpRequest into your own 
custom version of it, and then pass this custom version to further 
modules down the chain, to "make them believe" that this is the original 
request.
In your custom version, you override the original properties and methods 
of HttpRequest as you see fit, so that when the modules down the chain 
call these standard methods to get information about the request, they 
get your version, instead of the original.
In other words, your custom version of the request becomes like a "man 
in the middle" : some method calls it processes itself, responding with 
your modified parameters; the rest it lets through to the original 
HttpRequest object.  You choose which by re-implementing a method or not 
in your wrapper.

For example, suppose that your purpose was to modify the request, to add 
an additional HTTP header to it (because some module further down the 
chain is expecting it e.g.).
(I guess this is similar to adding a request parameter).

You would then create your own version of the original HttpRequest 
(using HttpRequestWrapper), and in it, create a method "getHeaders()". 
In that method, you would arrange it so that when a module down the 
chain calls HttpRequest.getHeaders(), it obtains the list of headers of 
the original request, *plus* the one you want to add.

It's a bit bizarre and feels a bit like overdoing it for someone used to 
other environments, but that's how it works, and I suppose there were 
good reasons to implement it this way.
One of the snags with it, is that when there are several possibilities 
for the module down the chain to get at something in the request, you 
have either to guess which one(s) they use, or redefine all of them in 
your wrapper.

I attach an example for you, with lots of warnings :
- it works, but I do not guarantee the style, nor that someone more 
qualified than me would find some deep flaw in it
- it contains a lot of stuff that you don't need, and I don't have time 
to take it all out. But I took out some, so as it is, it may not work 
anymore.

The attached filter's main purpose is to add a HTTP header to a request, 
before passing it on to the servlet that it filters.
The important part for you is

CustomRequest cr = new CustomRequest(request,context); //
(create request wrapper)
cr.setHeader(authIdHeaderName,authId); // add the new Id header

  and
class CustomRequest extends HttpServletRequestWrapper {

In the CustomRequest class :
I first call the HttpRequestWrapper constructor, passing the original 
request as parameter. That returns a HttpRequestWrapper object, 
containing the original HttpRequest object.
Then I build my own table of HTTP headers, first copying all the headers 
from the original request (there are more elegant ways to do this, I'm 
sure).
The "setHeader" method is used above by the filter, to add one or more 
aditional HTTP headers to this internal collection.
(You would probably need something similar to add request parameters)

Then I redefine the getHeaderNames() and getHeader() methods of the 
original HttpRequest object, so that they will return the headers from 
my own internal collection, instead of the headers of the original request.
Any module down the chain which calls "request".getHeaderNames() for 
instance, will get the names of the original request's headers, plus the 
ones I've added, and they will "believe" that they got the original article.
I only redefine these two methods, because I know that the downstream 
application only calls those (referring to the headers).
In your case, you would have to redefine the methods by which downstream 
applications would obtain the request parameters.
Any method of the original HttpRequest object not redefined here, will 
call the original methods of the HttpRequest object, and receive data 
based on that original request.

Does this help ?

Mime
View raw message