How to access to request body using WebFlux and Netty HttpClient

孤街醉人 提交于 2021-01-29 10:51:29

问题


I need to calculate some kind of digest of the request body using the WebClient of Webflux and this digest must be set into a HTTP header. Using the good old Spring MVC ClientHttpRequestInterceptor is easy because the request body is provided as an array of bytes.

The ExchangeFilterFunction does not provide access to the request body.

The body is sent as JSon and Spring uses Jackson in order to serialize Java objects, so an option could be serialize my Object into Json and calculate the digest on it, but this strategy has two drawbacks:

  • my code would repeat what Spring will do when the request is actually sent
  • there's no guarantee that the acutal bytes sent by Spring as a request are equal to what I've passed to the digest function

I suppose that I should use some low level API of Netty, but I can't find any example.


回答1:


I implemented the solution proposed by @rewolf and it worked, but I encountered an issue because of the multi-threading nature of WebFlux.

In fact, it's possible that the client request is saved into the thread-local map by one thread, but a different thread tries to get it, so a null value is returned.

For example, it happens if the request to be signed is created inside a Rest controller method which has a Mono as a request body parameter:

@PostMapping
public String execute(@RequestBody Mono<MyBody> body){

    Mono<OtherBody> otherBody = body.map(this::transformBodyIntoOtherBody);

    ...
    webClient.post()
    .body(otherBody)
    .exchange();
    ...
    
}

According to Reactor specs, the Reactor Context should be used instead of Thread Local.

I forked @rewolf project and implemented a solution based on Reactor Context: https://github.com/taxone/blog-hmac-auth-webclient




回答2:


This is not currently easy to do with WebClient. But there are ways to do so by intercepting the body post-serialization. This can be done by registering a custom encoder that intercepts the data after encoding, and the passes it to a custom HttpConnector to inject it as a header.

This blog post explains one way to achieve it: https://andrew-flower.com/blog/Custom-HMAC-Auth-with-Spring-WebClient

Edit: Currently this blog post doesn't take into account concurrent requests. See the accepted answer by Claodio for the modified approach.



来源:https://stackoverflow.com/questions/65532492/how-to-access-to-request-body-using-webflux-and-netty-httpclient

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!