0

So I have a org.springframework.stereotype.Controller and what I want to do is process the request normally if HTTP headers HA and HB are specified. But if the request has query parameters QA and QB specified, I want to redirect the request WITHOUT QA or QB, but WITH HTTP headers HA and HB such that HA has the value of QA and HB has the value of QB.

For example, if the incoming request is HTTP GET ~/rest/mortgage with HTTP headers x-name=foo and x-date=bar, I would process that request as is. But if the incoming request is HTTP GET ~/rest/mortgage?x-name=foo&x-date=bar, I want to redirect to myself with the request HTTP GET ~/rest/mortgage with HTTP headers x-name=foo and x-date=bar.

By doing this, I can have a single code path dealing with both styles of making the HTTP request just by adding a simple check at the controller level. This is because I pass the HttpServletRequest around to various parts of the code, so if I have the consistency of always having HA and HB instead of QA and QB, it reduces the cyclomatic complexity of the code.

Is this possible? And if so, how?

If this is not possible, I can achieve my desired result by defining my own wrapper for HttpServletRequest that does the transformation for me, but that's not as elegant of a solution.

jasons2645
  • 629
  • 1
  • 6
  • 10
  • This sounds more like something that a ServletFilter should handle. – jbx Sep 09 '14 at 17:46
  • possible duplicate of [How to use a servlet filter in Java to change an incoming servlet request url?](http://stackoverflow.com/questions/2725102/how-to-use-a-servlet-filter-in-java-to-change-an-incoming-servlet-request-url) – jbx Sep 09 '14 at 17:47
  • What's missing from that possible solution is how to add HA and HB (add HTTP headers in the transformed request). That solution provides an obvious answer to transforming the request otherwise. – jasons2645 Sep 10 '14 at 14:50
  • OK, you need to combine two ideas together. I posted a tentative answer below, check if it works. – jbx Sep 11 '14 at 14:35

1 Answers1

0

If you want to intercept the HTTP request you need to use a Servlet Filter.

In order to replace the URL you have to get the Dispatcher for the new URL, and then dispatch the request again with the forward() method.

Something like this:

servletRequest.getRequestDispatcher(modifiedURL)
              .forward(servletRequest, servletResponse);

However, you are not explicitly allowed to modify the HTTP headers. The way around this is to wrap the request and have a proxy object that handles this, by extending HttpServletRequestWrapper. It already implements the HttpServletRequest so you shouldn't have any issues using it wherever you are interacting with the original servlet request.

You can simply extend it and add your own method like addHeader() and keep an internal Map or something of the extra artificial headers you are adding. Then you have to just override getHeaderNames() and getHeader() to also combine the original headers with your own extra ones.

The last thing you will need to do is wrap your original servletRequest in your new wrappedServletRequest in your Filter. So something like this (where WrappedServletRequest is your new implementation that extends HttpServletRequestWrapper):

WrappedServletRequest wrappedServletRequest = 
                                     new WrappedServletRequest(servletRequest);
wrappedServletRequest.addHeader("yourHeader", "yourValue");

wrappedServletRequest.getRequestDispatcher(modifiedURL)
              .forward(wrappedServletRequest, servletResponse);

Remember to add your <filter> and <filter-mapping> of your Filter in your web.xml for it to work.

You might want to have a look at this article for more details. It has some more information as to why you have to do it this way.

I didn't try it myself, so comment below and confirm if you manage to get it to work.

jbx
  • 21,365
  • 18
  • 90
  • 144