1. Overview

In this quick tutorial, we'll go through different ways of setting a header on a service response, either for non-reactive endpoints or for APIs using Spring's 5 WebFlux framework.

We can find further information about this framework in previous posts.

2. Headers for Non-Reactive Components

If we want to set headers on single responses we can use HttpServletResponse or ResponseEntity objects.

On the other hand, if our objective is to add a filter to all or multiple responses, we'll need to configure a Filter.

2.1. Using HttpServletResponse

We simply have to add the HttpServletResponse object to our REST endpoint as an argument, then use the addHeader() method:

@GetMapping("/http-servlet-response")
public String usingHttpServletResponse(HttpServletResponse response) {
    response.addHeader("Baeldung-Example-Header", "Value-HttpServletResponse");
    return "Response with header using HttpServletResponse";
}

As shown in the example, we don't have to return the response object.

2.2. Using ResponseEntity

In this case, let's use the BodyBuilder provided by the ResponseEntity class:

@GetMapping("/response-entity-builder-with-http-headers")
public ResponseEntity<String> usingResponseEntityBuilderAndHttpHeaders() {
    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.set("Baeldung-Example-Header", 
      "Value-ResponseEntityBuilderWithHttpHeaders");

    return ResponseEntity.ok()
      .headers(responseHeaders)
      .body("Response with header using ResponseEntity");
}

The HttpHeaders class offers plenty of convenience methods to set the most common headers.

We can see more examples illustrating these points in our Github repo.

2.3. Adding a Header for All Responses

Now let's imagine we want to set a particular header to many of our endpoints.

Of course, it would be frustrating if we have to replicate the previous code on each mapping methods.

A better approach to accomplish this is by configuring a Filter in our service:

@WebFilter("/filter-response-header/*")
public class AddResponseHeaderFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setHeader(
          "Baeldung-Example-Filter-Header", "Value-Filter");
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // ...
    }

    @Override
    public void destroy() {
        // ...
    }
}

The @WebFilter annotation allows us to indicate the urlPatterns for which this Filter will become effective.

As we've pointed out in this article, in order to make our Filter discoverable by Spring, we need to add the @ServletComponentScan annotation to our Spring Application class:

@ServletComponentScan
@SpringBootApplication
public class ResponseHeadersApplication {

    public static void main(String[] args) {
        SpringApplication.run(ResponseHeadersApplication.class, args);
    }
}

We can avoid this last step if we don't need any of the functionality provided by @WebFilter, by using the @Component annotation in our Filter class instead.

3. Headers for Reactive Endpoints

Again, we'll see how to set headers on single endpoint responses using ServerHttpResponseResponseEntity or ServerResponse (for functional endpoints) classes and interfaces.

We'll also learn how to implement a Spring 5 WebFilter to add a header on all of our responses.

3.1. Using ServerHttpResponse

This approach is fairly similar to the HttpServletResponse counterpart:

@GetMapping("/server-http-response")
public Mono<String> usingServerHttpResponse(ServerHttpResponse response) {
    response.getHeaders().add("Baeldung-Example-Header", "Value-ServerHttpResponse");
    return Mono.just("Response with header using ServerHttpResponse");
}

3.2. Using ResponseEntity

We can use the ResponseEntity class exactly as we do for non-reactive endpoints:

@GetMapping("/response-entity")
public Mono<ResponseEntity<String>> usingResponseEntityBuilder() {
    String responseHeaderKey = "Baeldung-Example-Header";
    String responseHeaderValue = "Value-ResponseEntityBuilder";
    String responseBody = "Response with header using ResponseEntity (builder)";

    return Mono.just(ResponseEntity.ok()
      .header(responseHeaderKey, responseHeaderValue)
      .body(responseBody));
}

3.3. Using ServerResponse

The classes and interfaces introduced in the last two sub-sections can be used in @Controller annotated classes but are not suitable for the new Spring 5 Functional Web Framework.

If we want to set a header on a HandlerFunction then we'll need to get our hands on the ServerResponse interface:

public Mono<ServerResponse> useHandler(final ServerRequest request) {
     return ServerResponse.ok()
        .header("Baeldung-Example-Header", "Value-Handler")
        .body(Mono.just("Response with header using Handler"),String.class);
}

3.4. Adding a Header for All Responses

Lastly, Spring 5 provides a WebFilter interface to set a header on all the responses retrieved by a service:

@Component
public class AddResponseHeaderWebFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        exchange.getResponse()
          .getHeaders()
          .add("Baeldung-Example-Filter-Header", "Value-Filter");
        return chain.filter(exchange);
    }
}

4. Conclusion

In conclusion, we've learned many different ways of setting a header on a response, either if we want to set it on a single endpoint or if we want to configure all our rest APIs, even if we're migrating to the reactive stack, now we have the knowledge to do all these things.

As always, all the examples can be accessed in our Github repository, both the non-reactive ones and the ones using Spring 5 specific functionality.