Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to read HttpRequest parameters without consuming stream?

I am looking at the implementation of the HiddenMethodFilter in sitebricks here:

At line 65 there is the following code:

try {
    String methodName = httpRequest.getParameter(this.hiddenFieldName);
    if ("POST".equalsIgnoreCase(httpRequest.getMethod()) && !Strings.empty(methodName)) {
    ....

It checks if a specific parameter was set and uses that to wrap the request. However, in reading that parameter it will consume the stream and the eventual servlet will not be able read any data.

What would be the best way to avoid this? I implemented the HttpServletRequestWrapper here which reads the contents of the stream into a byte array. This however may use a lot of memory to store the requests.

private HttpServletRequestWrapper getWrappedRequest(HttpServletRequest httpRequest, final byte[] reqBytes)
   throws IOException {

final ByteArrayInputStream byteInput = new ByteArrayInputStream(reqBytes);
return new HttpServletRequestWrapper(httpRequest) {

  @Override
  public ServletInputStream getInputStream() throws IOException {
    ServletInputStream sis = new ServletInputStream() {

      @Override
      public int read() throws IOException {
        return byteInput.read();
      }
    };
    return sis;
  }
};
}

Is there a better way? can we read the parameter without consuming the stream? (Some thing similar to peek) can we reset the stream?

like image 564
Usman Ismail Avatar asked Nov 05 '22 01:11

Usman Ismail


1 Answers

If you are using POST requests and read parameters from the httpRequest this will affect the InputStream and you will have problems in other parts needing to read it.
This is stated in ServletRequest#getParameterjavadoc:

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.

The ServletInputStream is derived from InputStream and inherits the markSupported reset etc which are actually no-ops and so you can not reset a ServletInputStream.
This means that you will have to consume it.

like image 163
Jim Avatar answered Nov 12 '22 17:11

Jim