2

I have searched and seen a couple of answers about this problem, but still don't know how it's possible...

I'm asked to Implement a filter that returns response-time of an HTTP Request in the response header, eg. response-header: XX in order to get collected by a web analytics client side library.

here's my code :

public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpResp = (HttpServletResponse)response;
      long startTime = System.nanoTime();
      chain.doFilter(request, response);
      long endTime = System.nanoTime();
      httpResp.addHeader("response-time",endTime-startTime);
    }

as well I tried to user HttpServletResponseWrapper

I managed to modify the response using OutputStream but didn't succeed with setting the response headers.

Thanks,Jay

jsfviky
  • 183
  • 1
  • 11
Jay
  • 717
  • 11
  • 37
  • Can you show your new code. You can only setHeaders if the response is not already committed - do you get a response already committed error? – mmulholl Dec 04 '15 at 20:26
  • 1
    Also I should mention that this sort of model is broken. To set the header you need to prevent output from being written until you set your header. Then the time spent writing the output is not part of the response time recorded. – mmulholl Dec 04 '15 at 20:40
  • I've followed this example [How to use a filter to measure performance?](http://stackoverflow.com/a/14741213/4469946) , and managed to change the OutputStream, but what I need is adding a header response after the chain.doFilter.. maybe it is possible to add response header using the OutputStream ? – Jay Dec 05 '15 at 10:09
  • The outputStream encapsulates the response body and cannot be used to add headers. If you can add information to the end of the response body which the browser/client would ignore but your client side code can pick up that could work. – mmulholl Dec 05 '15 at 14:08
  • What you saying is it is not possible to add headers after chain.doFilter, since the response is already been sent to the user ? – Jay Dec 05 '15 at 18:15
  • The headers have to be sent before any part of the response body. If you create a wrapper which buffers the response so that you then send it from the filter, as per the answer below, you can add the header before you send the response but it will not include the time of sending the response in your response time because you have to send the header then the response. – mmulholl Dec 06 '15 at 14:09
  • I gave up that way, since I'm using [javax.ws.rs.core.Response] (http://docs.oracle.com/javaee/6/api/javax/ws/rs/core/Response.html) and ResponeBuilder, What I'm trying to do right now is using Spring AspectJ, and annotations @ Before, @ AfterReturning to catch all methods that returns type Response, but still I'm stuck! anyway thanks for you help :) – Jay Dec 06 '15 at 18:24
  • You can refer to [this answer] (https://stackoverflow.com/questions/32829124/adding-header-in-response-in-filter/32830377#32830377) – Harshad Vyawahare Oct 16 '18 at 14:54

1 Answers1

0

Extend wrapper utility class like HttpServletResponseWrapper (using custom output streams) and pass it to the chain doFilter() method. If you dont do that, after chain doFilter() returns, the original (not wrapped) response will be gone and you will not have a chance to modify it.

Here you can find an example: Looking for an example for inserting content into the response using a servlet filter

Community
  • 1
  • 1
jsfviky
  • 183
  • 1
  • 11
  • thanks for your response, I've used HttpServletResponseWrapper and managed to change the OutputStream, but I didn't succeed adding a response header. – Jay Dec 05 '15 at 10:07
  • but in your code you are not wrapping it. anyway, thats the way to do it. why you didnt succeed? did you get any type of error? if not, are you sure you did wrap/override correctly your writer-related methods to avoid response premature flush? – jsfviky Dec 05 '15 at 13:10