IWishIWasABarista
IWishIWasABarista

Reputation: 523

Spring - How can I add a header to ALL responses that I return?

Lets say I have an Spring REST API which has many, many responses being returned throughout the code.

If I wanted to return two specific headers with every single response I send out, How might I do that in a more intelligent way than manually adding them to every response before returning?

Is there a mechanism which allows me to catch the response before I send it, and add the headers?

EDIT : For future visitors asking this question. None of the answers here will actually result in a working interceptor. I suggest looking elsewhere.

Upvotes: 10

Views: 29550

Answers (5)

AllanT
AllanT

Reputation: 961

The way I got it to work was using ResponseBodyAdvice as shown in the example linked by Faxy.

Here is my solution for adding cache-control headers to every request:

@ControllerAdvice
public class HeaderModifierAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(final MethodParameter returnType, final Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(final Object body,
                                  final MethodParameter returnType,
                                  final MediaType selectedContentType,
                                  final Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  final ServerHttpRequest request,
                                  final ServerHttpResponse response) {
        response.getHeaders().add("Cache-Control", "no-cache, no-store, must-revalidate");
        response.getHeaders().add("Pragma", "no-cache");
        response.getHeaders().add("Expires", "0");
        return body;
    }
}

Upvotes: 11

IWishIWasABarista
IWishIWasABarista

Reputation: 523

The correct answer is to use a filter. Interceptors are not correct for this, regardless what people online say. Interceptors just don't work as desired.

Working solution is to create a filter as follows :

public class myAwesomeFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response, FilterChain filterChain)  throws ServletException, IOException {

        response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        response.addHeader("pragma", "no-cache");
        filterChain.doFilter(request, response);
    }
}

Then, in web.xml - you need the following :

<filter>
    <filter-name>sensitiveFormHeaderFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

Upvotes: 21

Moshe Arad
Moshe Arad

Reputation: 3733

You can easily do those using Handler Interceptors which allow you to modify the request processing lifecycle within Spring MVC. Interceptors are a very powerful tool that allows us to add functionality to the request processing lifecycle at 3 different points:

  1. before a controller handles a request
  2. after a controller method completed its code execution
  3. when the view is about to be rendered and sent back as the response to the client

I think option 2 will suit your needs.

Then you can write something like this:

public class MyInterceptor extends HandlerInterceptorAdapter {

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);

        //add your two headers on the response here
    }


}

step 2 is to register that interceptor in your configuration file, add the next lines to your XML configuration:

<mvc:interceptors>
   <bean Class="your interceptor class">
</mvc:interceptors>

from now on that interceptor will apply for every request.

Upvotes: 1

Ivan Kurinnyi
Ivan Kurinnyi

Reputation: 24

You may use spring interceptors for this purpose. Or there is more generic way to do this which not requires Spring for this. It's filter

Upvotes: -1

Faxy
Faxy

Reputation: 17

I believe you can implement the HandlerInterceptorAdapter interface and override the postHandle() method.

example

Upvotes: -2

Related Questions