Detect calls to RequestDispatcher.include() - java

I am programming a Servlet-Filter, that wraps the response and analyzes calls to addHeader() of the wrapped response. Before the response is committed to the client, it decorates it with some usefull headers (caching,compression etc), if appropriate.
This decoration is done, when ServletResponse.flushBuffer() is called on the wrapped response, or when the buffer-size is reached. But if the wrapped Servlet (or JSP-Page) is processing an include at that moment, no headers can be added to the response, because an include is forbidden to do that.
Therefore, I need to detect includes, so that I am able, to decorate the repsonse before the ressource is included.
The only way, I can think of, to accomplish that is, to wrap the request, catch calls to ServletRequest.getRequestDispatcher() and return a wrapped instance of RequestDispatcher, that informs me, when it's include-method is called. But since Servlet 3.0 there are also the methods ServletContext.getRequestDispatcher() and ServletContext.getNamedDispatcher(). I cannot catch that methods, because my filter cannot wrap the ServletContext.
Is there any other way to detect calls to RequestDispatcher.include()?

adding
<dispatcher>INCLUDE</dispatcher>
to filter-mapping seems to work refer

Related

What is a life of HttpServletRequest object?

I have doubt about HttpServletRequest life object. Is the request object destroyed after it got into controller?
The lifetime of an HttpServletRequest object is just that: the time of serving an HTTP Servlet request.
It may be created right before calling the servlet's doGet(), doPost() etc. methods, and may be destroyed right after that. It is only valid to use it during serving a request.
Note: However Servlet containers may reuse HttpServletRequest objects for multiple requests (and this is typically the case), but they will be "cleaned" or reset so no objects (like parameters or attributes) will leak between requests. This is simply due to performance issue: it is much faster and cheaper to reset an HttpServletRequest object than to throw away an existing one and create a new one.
In a typical Servlet container implementation if an HTTP request comes in, an HttpServletRequest is created right when the HTTP input data of the request is parsed by the Servlet container. The whole request might be lazily initialized (e.g. parameters might only be parsed and populated if they are really accessed e.g. via getParameter() method). Then this HttpServletRequest (which extends ServletRequest) is passed through the Servlet filters and then passed on to Servlet.service() which will dispatch the call to doGet(), doPost() etc based on the HTTP method (GET, POST, PUT etc.). Then the request will still be alive until the request-response pair cycles back throughout the filter chain. And then it will be destroyed or reset (before it is used for another HTTP request).

How to maintain request.getReader() with a filter?

After I added a filter to my app, I am not able to read anything from HttpServletRequest.getReader() in my controllers.
I am calling request.getParameter() a few times, but other than that my filter doesn't do much.
Okay I just thought through the problem and realized that for POST requests, calling getParameter() can cause a problem because POST params would typically be in the request body. The input stream will indeed be opened implicitly by the filter.
In my filter (and in my case) I need to check:
if (((HttpServletRequest) request).getMethod().equals("GET")) {...}

JSP, GET and POST parameters

I am required to do some small tasks with JSP; being very new to JSP I was wondering if there was any possibility to get only GET or only POST parameters from the HTTP request.
I have seen ServletRequest.getParameter (and alikes) but it seems that those methods get both GET and POST parameters. Is there a way to get only one of them, without parsing the URL or the request body myself? And if not, is there any precedence rule which values overwrite which (like POST parameters always overwriting GET parameters)?
Generally, requests should better be handled in servlets. They have doGet(request, response) and doPost(request, response) methods, to differentiate the two.
If you really insist on doing it in a JSP, you can differentiate the methods using request.getMethod(). It would return GET or POST.
Since this is homework, I guess the point is to learn how to use servlets and their doX methods, so do it that way.
Update: You can get the query string (request.getQueryString()), which is only the get parameters, and parse it, but I wouldn't say that's a common and good practice.
In JSP, you can look at the request object to determine what kind of request it was (GET or POST), but there's only one parameter map.
Try [Servlet + JSP]. At Servlet you can choose between doPost() or doGet()

Struts and logging HTTP POST request body

I'm trying to log the raw body of HTTP POST requests in our application based on Struts, running on Tomcat 6. I've found one previous post on SO that was somewhat helpful, but the accepted solution doesn't work properly in my case. The problem is, I want to log the POST body only in certain cases, and let Struts parse the parameters from the body after logging. Currently, in the Filter I wrote I can read and log the body from the HttpServletRequestWrapper object, but after that Struts can't find any parameters to parse, so the DispatchAction call (which depends on one of the parameters from the request) fails.
I did some digging through Struts and Tomcat source code, and found that it doesn't matter if I store the POST body into a byte array, and expose a Stream and a Reader based on that array; when the parameters need to get parsed, Tomcat's Request object accesses its internal InputStream, which has already been read by that time.
Does anyone have an idea how to implement this kind of logging correctly?
In fact, Struts doesn't parse the parameters, it relies on the Servlet container to do that. And once the container has read the inputStream to create the parameters Map, of course there is nothing left to read. And in the Tomcat implementation, if you read the inputStream first, then the getParameter* family of methods has nothing left to work on, since, as you correctly note, it doesn't use getInputStream or getReader but accesses internally its optimized reader.
So your only solution in your ServletRequestWrapper is to override getInputStream, getReader, AND the getParameter* family on which Struts relies to read the parameters. Maybe you can have a look at org.apache.catalina.util.RequestUtil to not duplicate the POST body parsing part.
What you have to do in your filter is read the post content in its entirety then when you go to pass the request on to the chain; back the input stream with your own. For example you read the post to file on disk, then when you call:
chain.doFilter(new ServletRequest() {}, response);
You can delegate most methods invocations of your class to the original request, but when it comes time to opening the input stream you need to read from your file on disk.
You need to make sure you don't leak resources as this will be invoked quite frequently and can hurt if done incorrectly.
The in the question linked filter example looks good and ought to work. Maybe you're defining it in the web.xml after the Struts dispatcher filter. It would then indeed be too late to parse and log the request body and still make it available for Struts. You need to declare this filter before the Struts dispatcher filter. The filter ordering matters, they are invoked in the order as they're definied in web.xml.

Removing MyFaces Orchestra's "conversationContext" GET parameter from static resources (css, images)

MyFaces Orchestra adds a ?conversationContext=x to each resource on a page. Since I'm not using the conversation scope for the public part of my project (only for the admin part), I'd like to get rid of that parameter for two reasons:
it breaks the browser caching of static resources
it's ugly :)
I'm now going to take a look at Orchestra's source-code, and perhaps bypass something, but it would be best if there is an option for this I'm unaware of
The answer to that question is simple, and at the same time a bit of a workaround.
MyFaces orchestra uses a wrapper around the original HttpServletResponse in order to encode the contesationContext parameter.
There are two options of using Orchestra - with an interceptor (JSF) and a Filter.
Both of them try to wrap the response, if it isn't already wrapped. So if both the orchestra Filter and the interceptor are used, the Filter comes firest, wraps the response object, and sets an attribute in the request, which indicates to the interceptor, that it shouldn't wrap the response again.
The Filter can be configured to match a certain URL pattern if conversationContext is to be added. However, for my needs, that pattern matcher was too simple, so I made my own filter instead. So in order to tell the interceptor NOT to wrap the response, all that has to be done is this:
httpRequest.setAttribute(
RequestParameterServletFilter.REQUEST_PARAM_FILTER_CALLED,
Boolean.TRUE);

Categories

Resources