This is an automated email from the ASF dual-hosted git repository.
zhangzicheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new c46ceed3f [ISSUE #3773] use #exchangeToMono replace #exchange (#3792)
c46ceed3f is described below
commit c46ceed3f5c098187fee0d8919110d9ac37a29e3
Author: dragon-zhang <[email protected]>
AuthorDate: Fri Sep 2 22:53:02 2022 +0800
[ISSUE #3773] use #exchangeToMono replace #exchange (#3792)
* [ISSUE #3773] use #exchangeToMono replace #exchange
* clean DataBuffer
* use Optional
* fix test case
* use Mono.fromCallable
* add cookies
---
.../shenyu/plugin/httpclient/WebClientPlugin.java | 30 ++++++++++++++--------
.../plugin/httpclient/WebClientPluginTest.java | 13 ++++++++++
2 files changed, 33 insertions(+), 10 deletions(-)
diff --git
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/WebClientPlugin.java
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/WebClientPlugin.java
index 3f81fe431..72ad7eb14 100644
---
a/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/WebClientPlugin.java
+++
b/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/WebClientPlugin.java
@@ -21,6 +21,7 @@ import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.enums.PluginEnum;
import org.apache.shenyu.common.enums.ResultEnum;
import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.reactive.function.BodyInserters;
@@ -31,14 +32,15 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.net.URI;
+import java.util.Optional;
/**
* The type Web client plugin.
*/
public class WebClientPlugin extends AbstractHttpClientPlugin<ClientResponse> {
-
+
private final WebClient webClient;
-
+
/**
* Instantiates a new Web client plugin.
*
@@ -47,20 +49,28 @@ public class WebClientPlugin extends
AbstractHttpClientPlugin<ClientResponse> {
public WebClientPlugin(final WebClient webClient) {
this.webClient = webClient;
}
-
+
@Override
protected Mono<ClientResponse> doRequest(final ServerWebExchange exchange,
final String httpMethod, final URI uri,
final HttpHeaders httpHeaders,
final Flux<DataBuffer> body) {
// springWebflux5.3 mark #exchange() deprecated. because #echange
maybe make memory leak.
// https://github.com/spring-projects/spring-framework/issues/25751
// exchange is deprecated, so change to {@link
WebClient.RequestHeadersSpec#exchangeToMono(Function)}
- // exchangeToMono has two important bug:
- // 1.exchangeToMono can cause NPE when response body is null
- // 2.download file with exchangeToMono can't open
return webClient.method(HttpMethod.valueOf(httpMethod)).uri(uri)
.headers(headers -> headers.addAll(httpHeaders))
.body(BodyInserters.fromDataBuffers(body))
- .exchange()
+ .exchangeToMono(response -> response.bodyToMono(byte[].class)
+ .flatMap(bytes -> Mono.fromCallable(() ->
Optional.ofNullable(bytes))).defaultIfEmpty(Optional.empty())
+ .flatMap(option -> {
+ final ClientResponse.Builder builder =
ClientResponse.create(response.statusCode())
+ .headers(headers ->
headers.addAll(response.headers().asHttpHeaders()))
+ .cookies(cookies ->
cookies.addAll(response.cookies()));
+ if (option.isPresent()) {
+ final DataBufferFactory dataBufferFactory =
exchange.getResponse().bufferFactory();
+ return
Mono.just(builder.body(Flux.just(dataBufferFactory.wrap(option.get()))).build());
+ }
+ return Mono.just(builder.build());
+ }))
.doOnSuccess(res -> {
if (res.statusCode().is2xxSuccessful()) {
exchange.getAttributes().put(Constants.CLIENT_RESPONSE_RESULT_TYPE,
ResultEnum.SUCCESS.getName());
@@ -71,17 +81,17 @@ public class WebClientPlugin extends
AbstractHttpClientPlugin<ClientResponse> {
exchange.getAttributes().put(Constants.CLIENT_RESPONSE_ATTR, res);
});
}
-
+
@Override
public int getOrder() {
return PluginEnum.WEB_CLIENT.getCode();
}
-
+
@Override
public String named() {
return PluginEnum.WEB_CLIENT.getName();
}
-
+
@Override
public boolean skip(final ServerWebExchange exchange) {
return skipExceptHttpLike(exchange);
diff --git
a/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/WebClientPluginTest.java
b/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/WebClientPluginTest.java
index f029c6a95..2b26962a8 100644
---
a/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/WebClientPluginTest.java
+++
b/shenyu-plugin/shenyu-plugin-httpclient/src/test/java/org/apache/shenyu/plugin/httpclient/WebClientPluginTest.java
@@ -34,6 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
@@ -159,8 +160,14 @@ public final class WebClientPluginTest {
}
private WebClient mockWebClientOK() {
+ final ClientResponse.Headers headers =
mock(ClientResponse.Headers.class);
+ when(headers.asHttpHeaders()).thenReturn(new HttpHeaders());
+
final ClientResponse mockResponse = mock(ClientResponse.class);
when(mockResponse.statusCode()).thenReturn(HttpStatus.OK);
+ when(mockResponse.headers()).thenReturn(headers);
+
when(mockResponse.bodyToMono(byte[].class)).thenReturn(Mono.just("{\"test\":\"ok\"}".getBytes()));
+ when(mockResponse.releaseBody()).thenReturn(Mono.empty());
given(this.exchangeFunction.exchange(this.captor.capture())).willReturn(Mono.just(mockResponse));
return WebClient.builder().baseUrl("/test")
.exchangeFunction(this.exchangeFunction)
@@ -170,8 +177,14 @@ public final class WebClientPluginTest {
}
private WebClient mockWebClientError() {
+ final ClientResponse.Headers headers =
mock(ClientResponse.Headers.class);
+ when(headers.asHttpHeaders()).thenReturn(new HttpHeaders());
+
final ClientResponse mockResponse = mock(ClientResponse.class);
when(mockResponse.statusCode()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR);
+ when(mockResponse.headers()).thenReturn(headers);
+ when(mockResponse.bodyToMono(byte[].class)).thenReturn(Mono.just(new
byte[0]));
+ when(mockResponse.releaseBody()).thenReturn(Mono.empty());
given(this.exchangeFunction.exchange(this.captor.capture())).willReturn(Mono.just(mockResponse));
return WebClient.builder().baseUrl("/test")
.exchangeFunction(this.exchangeFunction)