POST request sends parameters not through headers but in request body as stream which can be read only once. request.getParameter in case of POST request will not work as expected in servlet filter. This is why in servlet we have doGet and doPost method to handle GET and POST request respectively. In order to make stream to be read multiple times you have to wrap original request into customHttpServletRequestWrapper which copies the request body into instance variable i.e. payload from original request and override getInputStream method to return the stream from payload to be read multiple times in other filters and servlet. Optionally you can override other parameters method as well to get the data from this payload. In below example let?s override 2 methods i.e. getInputStream and getParameter.
CustomHttpRequestWrapper.java:
---------------------------------------------------------
package in.anyforum.util;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class CustomHttpRequestWrapper extends HttpServletRequestWrapper {
private final String payload;
private final JsonElement jsonData;
private static final Logger log = LoggerFactory.getLogger(CustomHttpRequestWrapper.class);
public CustomHttpRequestWrapper (HttpServletRequest request) throws IOException{
super(request);
// read the original payload into the payload variable
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
// read the payload into the StringBuilder
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
// make an empty string since there is no payload
stringBuilder.append("");
}
} catch (IOException ex) {
log.error("Error reading the request payload", ex);
throw new IOException("Error reading the request payload in CustomWrapper", ex);
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException iox) {
// ignore
}
}
}
payload = stringBuilder.toString();
JsonParser jsonParser = new JsonParser();
jsonData = (StringUtils.isEmpty(payload)?jsonParser.parse("{}"):jsonParser.parse(payload));
}
@Override
public ServletInputStream getInputStream () throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(payload.getBytes());
ServletInputStream inputStream = new ServletInputStream() {
public int read ()
throws IOException {
return byteArrayInputStream.read();
}
};
return inputStream;
}
@Override
public String getParameter(String paramName) {
//check first in request header, If not present then get it from payload
String paramValue = super.getParameter(paramName);
return null!=paramValue?paramValue:(jsonData.isJsonObject()?jsonData.getAsJsonObject().get(paramName).getAsString():"");
}
}
Further in Filter you can handle request as below and in chain.doFilter send this wrapped request as first parameter not the original request.
ServletFilter.java:
-----------------------------------
HttpServletRequestWrapper httpServletRequestWrapper = new CustomHttpRequestWrapper(httpReq);
String paramValue = httpServletRequestWrapper.getParameter(paramName);
//do something
chain.doFilter(httpServletRequestWrapper, httpResp);
5