Comment définir un en-tête sur une réponse avec Spring 5

Comment définir un en-tête sur une réponse avec Spring 5

1. Vue d'ensemble

Dans ce tutoriel rapide,we’ll go through different ways of setting a header on a service response, soit pour les points de terminaison non réactifs, soit pour les API utilisantSpring’s 5 WebFlux framework.

Nous pouvons trouver plus d'informations sur ce framework dansprevious posts.

2. En-têtes pour composants non réactifs

Si nous voulons définir des en-têtes sur des réponses uniques, nous pouvons utiliser des objetsHttpServletResponse ouResponseEntity.

D'un autre côté, si notre objectif est d'ajouter un filtre à toutes les réponses ou à plusieurs réponses, nous devrons configurer unFilter.

2.1. Utilisation deHttpServletResponse

Nous devons simplement ajouter l'objetHttpServletResponse à notre point de terminaison REST en tant qu'argument, puis utiliser la méthodeaddHeader():

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

Comme indiqué dans l'exemple, nous n'avons pas à renvoyer l'objet de réponse.

2.2. Utilisation deResponseEntity

Dans ce cas, utilisons lesBodyBuilder fournis par la classeResponseEntity:

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

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

La classeHttpHeaders offre de nombreuses méthodes pratiques pour définir les en-têtes les plus courants.

Nous pouvons voir plus d'exemples illustrant ces points enour Github repo.

2.3. Ajout d'un en-tête pour toutes les réponses

Imaginons maintenant que nous souhaitons définir un en-tête particulier pour plusieurs de nos points de terminaison.

Bien sûr, il serait frustrant de devoir répliquer le code précédent sur chaque méthode de mappage.

Une meilleure approche pour y parvenir est deconfiguring 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(
          "example-Example-Filter-Header", "Value-Filter");
        chain.doFilter(request, response);
    }

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

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

L'annotation@WebFilter nous permet d'indiquer leurlPatterns  pour lequel ceFilter will devient effectif.

Comme nous l'avons soulignéin this article, afin de rendre notreFilter découvrable par Spring, nous devons ajouter la annotation@ServletComponentScan à notre classe Spring Application:

@ServletComponentScan
@SpringBootApplication
public class ResponseHeadersApplication {

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

Nous pouvons éviter cette dernière étape si nous n'avons besoin d'aucune des fonctionnalités fournies par@WebFilter, en utilisant plutôt l'annotation@Component dans notre classeFilter.

3. En-têtes pour les points de terminaison réactifs

Encore une fois, nous verrons comment définir des en-têtes sur des réponses de point de terminaison unique à l'aide des classes et des interfacesServerHttpResponse,ResponseEntity  ouServerResponse (pour les points de terminaison fonctionnels).

Nous allons également apprendre à mettre en œuvre un Spring 5WebFilter pour ajouter un en-tête à toutes nos réponses.

3.1. Utilisation deServerHttpResponse

Cette approche est assez similaire à la contrepartie deHttpServletResponse:

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

3.2. Utilisation deResponseEntity

Nous pouvons utiliser la classeResponseEntity exactement comme nous le faisons pour les points de terminaison non réactifs:

@GetMapping("/response-entity")
public Mono> usingResponseEntityBuilder() {
    String responseHeaderKey = "example-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. Utilisation deServerResponse

Les classes et interfaces introduites dans les deux dernières sous-sections peuvent être utilisées dans les classes annotées@Controller mais ne conviennent pas pour les nouveauxSpring 5 Functional Web Framework.

Si nous voulons une interfaceto set a header on a HandlerFunction then we’ll need to get our hands on the ServerResponse:

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

3.4. Ajout d'un en-tête pour toutes les réponses

Enfin,Spring 5 provides a WebFilter interface to set a header on all the responses récupéré par un service:

@Component
public class AddResponseHeaderWebFilter implements WebFilter {

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

4. Conclusion

En conclusion, nous avons appris de nombreuses façons différentes de définir un en-tête sur une réponse, que ce soit si nous voulons le définir sur un seul point de terminaison ou si nous voulons configurer toutes nos API de repos, même si nous migrons vers la pile réactive , maintenant nous avons les connaissances nécessaires pour faire toutes ces choses.

Comme toujours, tous les exemples sont accessibles dans notre référentiel Github, à la fois lesnon-reactive ones et ceux utilisantSpring 5 specific functionality.