I\'m trying to accessing two http request parameters in a Java Servlet filter, nothing new here, but was surprised to find that the parameters have already been consumed! Be
I found good solution for any format of request body.
I tested for application/x-www-form-urlencoded
and application/json
both worked very well. Problem of ContentCachingRequestWrapper
that is designed only for x-www-form-urlencoded
request body, but not work with e.g. json. I found solution for json link. It had trouble that it didn't support x-www-form-urlencoded
.
I joined both in my code:
import org.apache.commons.io.IOUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class MyContentCachingRequestWrapper extends ContentCachingRequestWrapper {
private byte[] body;
public MyContentCachingRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
super.getParameterMap(); // init cache in ContentCachingRequestWrapper
body = super.getContentAsByteArray(); // first option for application/x-www-form-urlencoded
if (body.length == 0) {
body = IOUtils.toByteArray(super.getInputStream()); // second option for other body formats
}
}
public byte[] getBody() {
return body;
}
@Override
public ServletInputStream getInputStream() {
return new RequestCachingInputStream(body);
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
}
private static class RequestCachingInputStream extends ServletInputStream {
private final ByteArrayInputStream inputStream;
public RequestCachingInputStream(byte[] bytes) {
inputStream = new ByteArrayInputStream(bytes);
}
@Override
public int read() throws IOException {
return inputStream.read();
}
@Override
public boolean isFinished() {
return inputStream.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readlistener) {
}
}
}