The webapp's main purpose is to proxy requests to a backend server using the jEasy Extensible Proxy (J2EP) project (from Google SoC). This allows us to create a custom implementation of the logic for choosing a backend server to route requests to (linked with user sessions, the user's given permissions etc) with very little effort.
J2EP is implemented as a filter, with a second rewriting filter layered on top of the proxying filter. Originally, the module for J2EP was performing session validation and contained more logic for handling the server choices - the refactor moved this validation procedure out into its own filter, layered on top of the rewriting filter.
Once this was done, after lots of puzzling debug output, that the data in POST requests to the server was simply missing after passing through the proxy server. The detail that caught me out was hidden in the JavaDoc for
ServletRequest.getParameter(String name)
:public java.lang.String getParameter(java.lang.String name)
Returns the value of a request parameter as a String, or null if the parameter does not exist. Request parameters are extra information sent with the request. For HTTP servlets, parameters are contained in the query string or posted form data.
[..]
If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then reading the body directly via getInputStream() or getReader() can interfere with the execution of this method.
As it turns out, the code that was moved to the new, top layer filter called
getParameter()
in a couple of places. The J2EP proxy filter was later using getInputStream()
to pass the request parameters into the new outbound request. Even though it was after the initial parameter read, the reverse of the situation mentioned in the specification caused getInputStream()
to break and return an empty stream!I wish an
IllegalStateException
had simply been thrown rather than returning useless streams... *sigh*(note: this was under Apache Tomcat 5.5)