Discussion:
HttpServletRequest.getParameter() inside a valve
PAROLINI Antonio
2010-03-04 15:58:00 UTC
Permalink
Hello,

We are using a custom valve that scan the request parameters (POST AND GET) . If it find a parameter called "secuId" with a valide value , it set the session principals ( a kind of SSO).When this work most of the times, we have somes cases where calling the HttpServletRequest .getParameter() method within a valve has an impact to the called servlet.

Those cases are a "java.io.IOException: Connection reset by peer: Amount read didn't match content-length " for the WebObject servlet, and a EOFException in the invoker servlet in Jboss).

After some digging, I've found that calling HttpServletRequest .getParameter() does impact the request inputstream. See Craig R. McClanahan reply in this thread: http://markmail.org/message/xstjwbgz5r2ko2oe#query:+page:1+mid:xstjwbgz5r2ko2oe+state:results

So if I cannot use HttpServletRequest .getParameter() in my valve, what other option do i have ?

I've see that there is a request.getCoyoteRequest().getParameter() methode in the low level Tomcat API. Is this an option ?

Thanks in advance for your help,

Antonio
Christopher Schultz
2010-03-04 16:41:17 UTC
Permalink
Antonio,
Post by PAROLINI Antonio
We are using a custom valve that scan the request parameters (POST
AND GET) . If it find a parameter called "secuId" with a valide value
, it set the session principals ( a kind of SSO).When this work most
of the times, we have somes cases where calling the
HttpServletRequest .getParameter() method within a valve has an
impact to the called servlet.
It does: calling request.getParameter will consume the request body if
the following are true:

1. The protocol is HTTP or HTTPS
2. The method is POST
3. The Content-Type is application/x-www-form-urlencoded
[4. A call to request.getParameter*, which you're already doing]
Post by PAROLINI Antonio
Amount read didn't match content-length " for the WebObject servlet,
and a EOFException in the invoker servlet in Jboss).
That seems fairly straightforward: the client is sending a
Content-Length that doesn't match the amount of data sent: too few bytes
or too many. Can you post the whole stack trace?
Post by PAROLINI Antonio
So if I cannot use HttpServletRequest .getParameter() in my valve,
what other option do i have?
Well, if the Content-Length is wrong, you're going to have problems no
matter what. If request.getParameter* fails, I don't think that any
other APIs are going to help you...
Post by PAROLINI Antonio
I've see that there is a request.getCoyoteRequest().getParameter()
methode in the low level Tomcat API. Is this an option ?
I suspect you'll get the same exception from this level of code, too
(I'll even bet that method one calls the other).

If you must, I suppose you could read the request body yourself and
simply ignore the Content-Length mismatch.

Honestly, I would try to figure out why the Content-Type isn't matching
the request body length: this is likely to be a problem with whatever
client you are using. It's possible that it's an encoding mismatch.
Content-Length is supposed to mean number of octets, but it's possible
that your client is reporting the number of characters being sent, which
would probably be less than the number of bytes (though you get an
EOFException, so I'm guessing that the Content-Length is /larger/ than
the body you receive).

Strange.

- -chris
Rainer Frey
2010-03-05 07:18:10 UTC
Permalink
Post by Christopher Schultz
It does: calling request.getParameter will consume the request body if
1. The protocol is HTTP or HTTPS
2. The method is POST
3. The Content-Type is application/x-www-form-urlencoded
[4. A call to request.getParameter*, which you're already doing]
Post by PAROLINI Antonio
Amount read didn't match content-length " for the WebObject servlet,
and a EOFException in the invoker servlet in Jboss).
That seems fairly straightforward: the client is sending a
Content-Length that doesn't match the amount of data sent: too few bytes
or too many. Can you post the whole stack trace?
Could this be because the input stream of the body is already consumed and the
servlet can't read <Content-Length> number of bytes anymore, even when the
Content-Length header was originally correct?

Rainer
PAROLINI Antonio
2010-03-05 09:35:42 UTC
Permalink
Hey,

Thanks for your analyse.

I guess the only way out of this is to prevent the use of getparameter() in case of a HTTP post. This may be ok for us, as our secuId is sent using the querystring, thus HTTP GET.

I've seen a place where request.getParameter() is used thus: in FormAuthenticator. But after son digging, I've seen that in that case a new request object is build from scratch by the valve and resent to the target servlet.

-antonio
Post by Christopher Schultz
Post by PAROLINI Antonio
Amount read didn't match content-length " for the WebObject servlet,
and a EOFException in the invoker servlet in Jboss).
That seems fairly straightforward: the client is sending a
Content-Length that doesn't match the amount of data sent: too few bytes
or too many. Can you post the whole stack trace?
Here is the Webobject servlet stacktrace:

java.io.IOException: Connection reset by peer: Amount read didn't match content-length
at com.webobjects.appserver._private.WONoCopyPushbackInputStream.read(WONoCopyPushbackInputStream.java:175)
at com.webobjects.appserver._private.WOInputStreamData._extractBytesFromInputStream(WOInputStreamData.java:105)
at com.webobjects.appserver._private.WOInputStreamData.bytesNoCopy(WOInputStreamData.java:137)
at com.webobjects.foundation.NSData._bytesNoCopy(NSData.java:502)
at com.webobjects.appserver.WOMessage.contentString(WOMessage.java:651)
at Application.dispatchRequest(Unknown Source)
at com.webobjects.jspservlet._WOApplicationWrapper.servletDispatchRequest(_WOApplicationWrapper.java:118)
at com.webobjects.jspservlet.WOServletAdaptor._handleRequest(WOServletAdaptor.java:581)
at com.webobjects.jspservlet.WOServletAdaptor.doPost(WOServletAdaptor.java:548)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.borland.pso.security.web.SecurityServletFilter.doFilter(SecurityServletFilter.java:41)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:543)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at hug.jade.security.tomcat.valve.HugSSOValve.in

Loading...