Generic Top

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this quick tutorial, we'll explore the different ways of setting a header on a service response, either for non-reactive endpoints or APIs, using Spring 5's 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.

In contrast, 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, and 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 above example, we don't have to return the response object.

2.2. Using ResponseEntity

In this case, we'll 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 had to replicate the previous code on each mapping method.

A better approach to accomplishing 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 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);
    }
}

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

3. Headers for Reactive Endpoints

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

We'll also discuss 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 aren't 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

Finally, 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 this article, we learned many different ways of setting a header on a response. Now whether we want to set it on a single endpoint, configure all our rest APIs, or even migrate to the reactive stack, we have the knowledge necessary.

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

Generic bottom

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE
Generic footer banner
Comments are closed on this article!