Created
March 18, 2012 12:48
-
-
Save calo81/2071634 to your computer and use it in GitHub Desktop.
Filter for reading and logging HttpServletRequest body, and resetting the input stream
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.paddypower.financials.market.management.rest.logging; | |
import java.io.BufferedReader; | |
import java.io.ByteArrayInputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import javax.servlet.Filter; | |
import javax.servlet.FilterChain; | |
import javax.servlet.FilterConfig; | |
import javax.servlet.ServletException; | |
import javax.servlet.ServletInputStream; | |
import javax.servlet.ServletRequest; | |
import javax.servlet.ServletResponse; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletRequestWrapper; | |
import org.apache.commons.io.IOUtils; | |
public class LoggerFilter implements Filter { | |
private Auditor auditor; | |
public void destroy() { | |
// Nothing to do | |
} | |
public void doFilter(ServletRequest request, ServletResponse response, | |
FilterChain chain) throws IOException, ServletException { | |
ResettableStreamHttpServletRequest wrappedRequest = new ResettableStreamHttpServletRequest( | |
(HttpServletRequest) request); | |
// wrappedRequest.getInputStream().read(); | |
String body = IOUtils.toString(wrappedRequest.getReader()); | |
auditor.audit(wrappedRequest.getRequestURI(),wrappedRequest.getUserPrincipal(), body); | |
wrappedRequest.resetInputStream(); | |
chain.doFilter(wrappedRequest, response); | |
} | |
public void init(FilterConfig arg0) throws ServletException { | |
// Nothing to do | |
} | |
private static class ResettableStreamHttpServletRequest extends | |
HttpServletRequestWrapper { | |
private byte[] rawData; | |
private HttpServletRequest request; | |
private ResettableServletInputStream servletStream; | |
public ResettableStreamHttpServletRequest(HttpServletRequest request) { | |
super(request); | |
this.request = request; | |
this.servletStream = new ResettableServletInputStream(); | |
} | |
public void resetInputStream() { | |
servletStream.stream = new ByteArrayInputStream(rawData); | |
} | |
@Override | |
public ServletInputStream getInputStream() throws IOException { | |
if (rawData == null) { | |
rawData = IOUtils.toByteArray(this.request.getReader()); | |
servletStream.stream = new ByteArrayInputStream(rawData); | |
} | |
return servletStream; | |
} | |
@Override | |
public BufferedReader getReader() throws IOException { | |
if (rawData == null) { | |
rawData = IOUtils.toByteArray(this.request.getReader()); | |
servletStream.stream = new ByteArrayInputStream(rawData); | |
} | |
return new BufferedReader(new InputStreamReader(servletStream)); | |
} | |
private class ResettableServletInputStream extends ServletInputStream { | |
private InputStream stream; | |
@Override | |
public int read() throws IOException { | |
return stream.read(); | |
} | |
} | |
} | |
public void setAuditor(Auditor auditor) { | |
this.auditor = auditor; | |
} | |
} |
This is awesome !!
Thanks. The following code with some changes from your code works for me :
private static class ResettableStreamHttpServletRequest extends HttpServletRequestWrapper {
private byte[] rawData;
private HttpServletRequest request;
private ResettableServletInputStream servletStream;
private ResettableStreamHttpServletRequest(HttpServletRequest request) {
super(request);
this.request = request;
servletStream = new ResettableServletInputStream();
}
public void resetInputStream() {
servletStream.stream = new ByteArrayInputStream(rawData);
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return servletStream;
}
@Override
public BufferedReader getReader() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return new BufferedReader(new InputStreamReader(servletStream));
}
}
private static class ResettableServletInputStream extends ServletInputStream {
private InputStream stream;
@Override
public int read() throws IOException {
return stream.read();
}
@Override
public boolean isFinished() {
try {
int available = stream.available();
return available == 0;
} catch (IOException e) {
return true;
}
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) { }
}
Thanks ! Really useful !!! 😄
I am calling Http POST to the REST endpoint, but making XML request, in my case 3rd party system can only make the SOAP request, now I need to remove soapenv:Envelope from the request and only pass the xml tags. I am using Spring Boot application.
Is there any way to read the request and update the POST data?
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:wer.com:dms:wsdls:organization">
<soapenv:Header/>
<soapenv:Body>
<urn:getProfile>
<getProfileRequest>
<patientId>160166</patientId>
</getProfileRequest>
</urn:getProfile>
</soapenv:Body>
</soapenv:Envelope>
Thank you.
It was really helpful.
Here is my working solution, that is up-to-date with packages' versions.
private static final class CopyableHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] rawData;
private HttpServletRequest request;
private CopyableServletInputStream servletInputStream;
private static final class CopyableServletInputStream extends ServletInputStream {
private InputStream stream;
public CopyableServletInputStream(InputStream stream) {
this.stream = stream;
}
@Override
public boolean isFinished() {
try {
int remainingBytes = stream.available();
return 0 == remainingBytes;
} catch (IOException ex) {
return false;
}
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener listener) { }
@Override
public int read() throws IOException {
return stream.read();
}
}
private CopyableHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public ServletInputStream getInputStream() throws IOException {
copyBodyDataIfNecessary();
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
copyBodyDataIfNecessary();
return new BufferedReader(new InputStreamReader(servletInputStream));
}
public void copyBodyDataIfNecessary() throws IOException {
if(null == rawData) {
rawData = IOUtils.toByteArray(request.getReader(), "utf-8");
servletInputStream = new CopyableServletInputStream(new ByteArrayInputStream(rawData));
}
}
public void resetStream() throws IOException {
this.servletInputStream = new CopyableServletInputStream(new ByteArrayInputStream(rawData));
}
}
very good!!!
Thank you every one, a little change because not working in my project by a cast wrong
private static final class CopyableHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] rawData;
private final HttpServletRequest request;
private CopyableServletInputStream servletInputStream;
private static final class CopyableServletInputStream extends ServletInputStream {
private final InputStream stream;
public CopyableServletInputStream(InputStream stream) {
this.stream = stream;
}
@Override
public boolean isFinished() {
try {
int remainingBytes = stream.available();
return 0 == remainingBytes;
} catch (IOException ex) {
return false;
}
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener listener) {
}
@Override
public int read() throws IOException {
return stream.read();
}
}
private CopyableHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public ServletInputStream getInputStream() throws IOException {
copyBodyDataIfNecessary();
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
copyBodyDataIfNecessary();
return new BufferedReader(new InputStreamReader(servletInputStream));
}
public void copyBodyDataIfNecessary() throws IOException {
if (null == rawData) {
rawData = IOUtils.toByteArray(this.request.getInputStream());
servletInputStream = new CopyableServletInputStream(new ByteArrayInputStream(rawData));
}
}
public void resetStream() throws IOException {
this.servletInputStream = new CopyableServletInputStream(new ByteArrayInputStream(rawData));
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Concerning the encoding problem, this might work, but I haven't tried it: