Sunday, January 11, 2009

Read Request Body in Filter

Is it possible to intercept HTTP Request in order to read HTTP Request Body (HTTP Request Payload) before it is served by target servlet or JSP?

The answer is yes. You can use Servlet Filter to read, "filter" or modify ServletRequest (HTTPServletRequest) object before the request object is sent to and serve by the final servlet.

What if I read a request body within a servlet filter, is the body still going to be available to be read again by the servlet, or can it be read only once?

Yes, but it is a little bit tricky.
Because of the fact that the request body can be read only once. If you read the body in a filter, the target servlet will not be able to re-read it and this will also cause IllegalStateException. You will need ServletRequestWrapper or its child: HttpServletRequestWrapper so that you can read HTTP request body and then the servlet can still read it later.

public class MyRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public MyRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
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 {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}

@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}

@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}

public String getBody() {
return this.body;
}
}

The first step is to create a class that extends HttpServletRequestWrapper. Then, use the constructor to read HTTP Request body and store it in "body" variable. The final step is to override getInputStream() and getReader() so that the final servlet can read HTTP Request Body without causing IllegalStateException.

Here's how to use RequestWrapper in the filter.

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {

Throwable problem = null;

MyRequestWrapper myRequestWrapper = new MyRequestWrapper((HttpServletRequest) request);

String body = myRequestWrapper.getBody();
String clientIP = myRequestWrapper.getRemoteHost();
int clientPort = request.getRemotePort();
String uri = myRequestWrapper.getRequestURI();

System.out.println(body);
System.out.println(clientIP);
System.out.println(clientPort);
System.out.println(uri);

chain.doFilter(myRequestWrapper, response);
}

47 comments:

  1. Thank you for the code sample, I have been trying to do this myself. However, after adding the filter the downstream servlet loses all its http post parameters. The parameters re-appear only after the above filter is removed. Running OpenJDK 6 with Tomcat 6.0.16

    ReplyDelete
    Replies
    1. Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a Java developer learn from Java Training in Chennai. or learn thru Java Online Training in India . Nowadays Java has tons of job opportunities on various vertical industry.

      Delete
  2. There is a problem with this code...
    When I use POST request to submit my data and try to read some parameter with myRequestWrapper.getParameter("paramName") I get null. I suppose this wrapper should implement its own getParameter(String) method...

    ReplyDelete
  3. In actuality, the code above will not work if the call is made to the InputStream, and later you request any parameter. You must override all of the parameter methods for this to work.

    ReplyDelete
  4. We use this code and found it very useful.
    but we found a bug- when reading the body from the input stream, you use the default charset of the machine:
    bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

    instead, you should probably use the request body charset.
    so you should change the above line to this line:
    bufferedReader = new BufferedReader(new InputStreamReader(inputStream, request.getCharacterEncoding()));

    ReplyDelete
  5. Thanks sir, but how can I get the request body from another class? I have a class that makes the md5 digest of that request body.

    Thanks a lot in advance.

    ReplyDelete
  6. Very good post. PRECISELY what I needed to know!

    ReplyDelete
  7. Under which class is the doFilter() Method? Do I insert it in the servlet class?

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. Thanks for the awesome work. I was wrong doubting your code. (THUMBS UP)

    ReplyDelete
  12. I found your blog while searching for the updates, I am happy to be here. Very useful content and also easily understandable providing.. Believe me I did wrote an post about tutorials for beginners with reference of your blog. 
    rpa training in bangalore
    best rpa training in bangalore
    RPA training in bangalore
    rpa course in bangalore
    rpa training in chennai
    rpa online training

    ReplyDelete
  13. That was a great message in my carrier, and It's wonderful commands like mind relaxes with understand words of knowledge by information's.
    python training in chennai
    python course in chennai
    python training in bangalore

    ReplyDelete
  14. Thank you for taking the time to provide us with your valuable information. We strive to provide our candidates with excellent care and we take your comments to heart.As always, we appreciate your confidence and trust in us
    python training in chennai
    python course in chennai
    python training in bangalore

    ReplyDelete
  15. Hmm, it seems like your site ate my first comment (it was extremely long) so I guess I’ll just sum it up what I had written and say, I’m thoroughly enjoying your blog. I as well as an aspiring blog writer, but I’m still new to the whole thing. Do you have any recommendations for newbie blog writers? I’d appreciate it.
    AWS Course Interview Questions and Answers for Freshers | AWS Interviews Questions and Answers for Devops
    AWS Tutorial – Besant Technologies
    AWS Interview questions and answers for Sysops |AWS Interview Question and Answers BlogSpot
    AWS Tutorial For Beginners | AWS Tutorial with AWS Training Videos

    ReplyDelete
  16. The post is written in very a good manner and it entails many useful information for me. I am happy to find your distinguished way of writing the post. Now you make it easy for me to understand and implement the concept.
    AWS Training in pune
    AWS Online Training

    ReplyDelete
  17. I am amzaed by the way you have explained things in this post. This post is quite interesting and i am looking forward to read more of your posts.
    redmi note service center in chennai
    redmi service center in velachery
    redmi service center in t nagar
    redmi service center in vadapalani

    ReplyDelete
  18. This comment has been removed by the author.

    ReplyDelete
  19. Great Post,really it was very helpful for us.
    Thanks a lot for sharing!
    I found this blog to be very useful!!
    JAVA training in Bangalore

    ReplyDelete
  20. does not work the code above even with the refactorization

    ReplyDelete
  21. සතුටින් හා ප්රීතිමත් දවසක්. ලිපිය හුවමාරු කර ගැනීම සඳහා ඔබට ස්තූතියි

    máy phun tinh dầu

    máy khuếch tán tinh dầu tphcm

    máy khuếch tán tinh dầu hà nội

    máy xông phòng ngủ

    ReplyDelete
  22. Thanks for sharing the valuable information here. So i think i got some useful information with this content. Thank you and please keep update like this informative details.


    erp software development company in us
    erp software company in us
    list of erp software companies in us
    erp in chennai
    list of erp software companies in chennai
    Latest CRM Software

    ReplyDelete
  23. nice blog
    get best placement at VSIPL

    get digital marketing services
    seo network point

    ReplyDelete
  24. nice blog
    get best placement at VSIPL

    get digital marketing services
    seo network point

    ReplyDelete
  25. Thanks for sharing the valuable information here. So i think i got some useful information with this content. Thank you and please keep update like this informative details.


    wedding catering services in chennai
    birthday catering services in chennai
    corporate catering services in chennai
    taste catering services in chennai
    veg Catering services in chennai

    ReplyDelete
  26. Thanks for sharing it.I got Very significant data from your blog.your post is actually Informatve .I'm happy with the data that you provide.thanks


    click here
    see more
    visit us
    website
    more details





    ReplyDelete
  27. Thanks for your excellent blog and giving great kind of information. So useful. Nice work keep it up thanks for sharing the knowledge.
    Visit us
    Click Here
    For More Details
    Visit Website
    See More

    ReplyDelete
  28. Thanks for sharing it.I got Very valuable information from your blog.your post is really very Informatve.I’m satisfied with the information that you provide for me.

    aws course
    aws certification
    aws devlopment
    aws syllabus

    ReplyDelete