diff --git a/spring/webflux/webclient.md b/spring/webflux/webclient.md index 42d8424..2d0bbf1 100644 --- a/spring/webflux/webclient.md +++ b/spring/webflux/webclient.md @@ -394,4 +394,61 @@ WebClient client = webClient.mutate() }) .build(); ``` +### filter处理response +在使用filter时,需要`确保response content总是被消费`: +- 当filter在处理response时,需要确保filter总是: + - 消费response content + - 或将response传递到下游 + +示例代码如下所示: +```java +public ExchangeFilterFunction renewTokenFilter() { + return (request, next) -> next.exchange(request).flatMap(response -> { + if (response.statusCode().value() == HttpStatus.UNAUTHORIZED.value()) { + return response.releaseBody() + .then(renewToken()) + .flatMap(token -> { + ClientRequest newRequest = ClientRequest.from(request).build(); + return next.exchange(newRequest); + }); + } else { + return Mono.just(response); + } + }); +} +``` + +如下示例创建了自定义的filter,用于计算POST和PUT的`multipart/form-data`请求的`Content-Length` +```java +public class MultipartExchangeFilterFunction implements ExchangeFilterFunction { + + @Override + public Mono filter(ClientRequest request, ExchangeFunction next) { + if (MediaType.MULTIPART_FORM_DATA.includes(request.headers().getContentType()) + && (request.method() == HttpMethod.PUT || request.method() == HttpMethod.POST)) { + return next.exchange(ClientRequest.from(request).body((outputMessage, context) -> + request.body().insert(new BufferingDecorator(outputMessage), context)).build() + ); + } else { + return next.exchange(request); + } + } + + private static final class BufferingDecorator extends ClientHttpRequestDecorator { + + private BufferingDecorator(ClientHttpRequest delegate) { + super(delegate); + } + + @Override + public Mono writeWith(Publisher body) { + return DataBufferUtils.join(body).flatMap(buffer -> { + getHeaders().setContentLength(buffer.readableByteCount()); + return super.writeWith(Mono.just(buffer)); + }); + } + } +} +``` +