Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpServletRequestWrapper, example implementation for setReadListener / isFinished / isReady?

I am trying to adapt a HttpServletRequestWrapper (see How to read InputStream multiple times) to be able te read the HTTP Post body after consuming it in a filter. Now I run into a challenge on how to implement the ServletInputStream. As of spec 3.1 there are new methods that have to be implemented.

  • isFinished
  • isReady
  • setReadListener

I am looking for examples or some code on how these methods can be implemented. Any hints?

like image 336
Marco Avatar asked Mar 23 '15 10:03

Marco


2 Answers

Example implementation:

import com.google.common.primitives.Bytes;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public class AuthenticationRequestWrapper extends HttpServletRequestWrapper {

    // tag::variables[]
    private byte[] requestBody = new byte[0];
    private boolean bufferFilled = false;
    // end::variables[]

    /**
     - Constructs a request object wrapping the given request.
     *
     - @param request The request to wrap
     - @throws IllegalArgumentException if the request is null
     */
    public AuthenticationRequestWrapper(HttpServletRequest request) {
        super(request);
    }


    // tag::getRequestBody[]
    public byte[] getRequestBody() throws IOException {
        if (bufferFilled) {
            return Arrays.copyOf(requestBody, requestBody.length);
        }

        InputStream inputStream = super.getInputStream();

        byte[] buffer = new byte[102400]; // 100kb buffer

        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            requestBody = Bytes.concat(this.requestBody, Arrays.copyOfRange(buffer, 0, bytesRead)); // <1>
        }

        bufferFilled = true;

        return requestBody;
    }
    // end::getRequestBody[]

    // tag::getInputStream[]
    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new CustomServletInputStream(getRequestBody()); // <1>
    }
    // end::getInputStream[]

    private static class CustomServletInputStream extends ServletInputStream {

        private ByteArrayInputStream buffer;

        public CustomServletInputStream(byte[] contents) {
            this.buffer = new ByteArrayInputStream(contents);
        }

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

        @Override
        public boolean isFinished() {
            return buffer.available() == 0;
        }

        @Override
        public boolean isReady() {
            return true;
        }

        @Override
        public void setReadListener(ReadListener listener) {
            throw new RuntimeException("Not implemented");
        }
    }
}
like image 163
Marco Avatar answered Oct 17 '22 21:10

Marco


you can check MockHttpServletRequest in the spring framework

The source code could be found here

Since Spring is open source with Apache2 license you can start from the code and build your own version.

like image 29
Giovanni Avatar answered Oct 17 '22 20:10

Giovanni