package de.otto.hmac.authentication; import com.google.common.io.ByteSource; import com.google.common.io.ByteStreams; import com.google.common.io.FileBackedOutputStream; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.IOException; import java.io.InputStream; /** * A wrapper for a HttpServletRequest. * * The wrapper is needed to read the request body multiple times, for example during the authentication process * and later in the call stack to read the request body. */ public class WrappedRequest extends HttpServletRequestWrapper implements AutoCloseable { private FileBackedOutputStream body = new FileBackedOutputStream(10*1000*1000, true); /** * Factory method used to create a WrappedRequest, wrapping a HttpServletRequest. * * @param request the HttServletRequest * @return WrappedRequest * @throws IOException if reading the request body fails. */ public static WrappedRequest wrap(final HttpServletRequest request) throws IOException { if (request instanceof WrappedRequest) { return (WrappedRequest) request; } return new WrappedRequest(request); } @Override public ServletInputStream getInputStream() throws IOException { return new WrappedServletInputStream(getBody().openBufferedStream()); } public ByteSource getBody() { return body.asByteSource(); } private WrappedRequest(final HttpServletRequest request) throws IOException { super(request); if (request.getInputStream() != null) { try (final InputStream inputStream = request.getInputStream()) { ByteStreams.copy(inputStream, body); } } } @Override public void close() throws IOException { body.close(); } }