This is an automated email from the ASF dual-hosted git repository.
xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 15d8c66 fix fallbackUri not work in resilience4j plugin issue (#2938)
15d8c66 is described below
commit 15d8c66d990aba04bc72825ce9a412ec6388c038
Author: Han Gao <[email protected]>
AuthorDate: Fri Feb 25 18:13:11 2022 +0800
fix fallbackUri not work in resilience4j plugin issue (#2938)
---
.../plugin/resilience4j/executor/Executor.java | 30 +++++++++++++++++-----
.../executor/CombinedExecutorTest.java | 25 ++++++++++++++++++
2 files changed, 48 insertions(+), 7 deletions(-)
diff --git
a/shenyu-plugin/shenyu-plugin-resilience4j/src/main/java/org/apache/shenyu/plugin/resilience4j/executor/Executor.java
b/shenyu-plugin/shenyu-plugin-resilience4j/src/main/java/org/apache/shenyu/plugin/resilience4j/executor/Executor.java
index e5ef2e4..91e67c5 100644
---
a/shenyu-plugin/shenyu-plugin-resilience4j/src/main/java/org/apache/shenyu/plugin/resilience4j/executor/Executor.java
+++
b/shenyu-plugin/shenyu-plugin-resilience4j/src/main/java/org/apache/shenyu/plugin/resilience4j/executor/Executor.java
@@ -17,23 +17,22 @@
package org.apache.shenyu.plugin.resilience4j.executor;
+import com.google.common.base.Strings;
import io.github.resilience4j.circuitbreaker.CallNotPermittedException;
import io.github.resilience4j.ratelimiter.RequestNotPermitted;
import org.apache.commons.lang3.StringUtils;
import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
-import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
import org.apache.shenyu.common.utils.UriUtils;
import org.apache.shenyu.plugin.resilience4j.Resilience4JPlugin;
import org.apache.shenyu.plugin.resilience4j.conf.Resilience4JConf;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.web.reactive.DispatcherHandler;
+import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
-import java.util.Objects;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
@@ -65,10 +64,27 @@ public interface Executor {
if (StringUtils.isBlank(uri)) {
return withoutFallback(exchange, t);
}
- DispatcherHandler dispatcherHandler =
SpringBeanUtils.getInstance().getBean(DispatcherHandler.class);
- ServerHttpRequest request =
exchange.getRequest().mutate().uri(Objects.requireNonNull(UriUtils.createUri(uri))).build();
- ServerWebExchange mutated = exchange.mutate().request(request).build();
- return dispatcherHandler.handle(mutated);
+
+ ServerHttpResponse response = exchange.getResponse();
+ ServerHttpRequest request = exchange.getRequest();
+ // avoid redirect loop, return error.
+ boolean isSameUri;
+ if (uri.startsWith("https") || uri.startsWith("http")) {
+ isSameUri = request.getURI().toString().equals(uri);
+ } else {
+ String params = Strings.isNullOrEmpty(request.getURI().getQuery())
? "" : request.getURI().getQuery();
+ String reqQueryWithParams = request.getURI().getPath() + params;
+ isSameUri = reqQueryWithParams.equals(uri);
+ }
+
+ if (isSameUri) {
+ return withoutFallback(exchange, t);
+ }
+
+ // redirect to fallback uri.
+ response.setStatusCode(HttpStatus.FOUND);
+ response.getHeaders().setLocation(UriUtils.createUri(uri));
+ return Mono.empty();
}
/**
diff --git
a/shenyu-plugin/shenyu-plugin-resilience4j/src/test/java/org/apache/shenyu/plugin/resilience4j/executor/CombinedExecutorTest.java
b/shenyu-plugin/shenyu-plugin-resilience4j/src/test/java/org/apache/shenyu/plugin/resilience4j/executor/CombinedExecutorTest.java
index ba67254..d995ac7 100644
---
a/shenyu-plugin/shenyu-plugin-resilience4j/src/test/java/org/apache/shenyu/plugin/resilience4j/executor/CombinedExecutorTest.java
+++
b/shenyu-plugin/shenyu-plugin-resilience4j/src/test/java/org/apache/shenyu/plugin/resilience4j/executor/CombinedExecutorTest.java
@@ -25,9 +25,14 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.http.HttpStatus;
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.web.server.MockServerWebExchange;
+import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -71,4 +76,24 @@ public final class CombinedExecutorTest {
.expectError(RuntimeException.class)
.verify();
}
+
+ @Test
+ public void fallbackUriTest() {
+ Resilience4JConf conf = mock(Resilience4JConf.class);
+ when(conf.getId()).thenReturn("SHENYU");
+
when(conf.getRateLimiterConfig()).thenReturn(RateLimiterConfig.ofDefaults());
+
when(conf.getTimeLimiterConfig()).thenReturn(TimeLimiterConfig.ofDefaults());
+
when(conf.getCircuitBreakerConfig()).thenReturn(CircuitBreakerConfig.ofDefaults());
+
+ ServerWebExchange exchange =
MockServerWebExchange.from(MockServerHttpRequest.get("localhost").build());
+
+ StepVerifier.create(combinedExecutor.run(Mono.error(new
RuntimeException()), t -> combinedExecutor.fallback(exchange,
"https://example.com", t),
+ conf))
+ .expectSubscription()
+ .expectComplete()
+ .verify();
+
+ assertEquals(HttpStatus.FOUND, exchange.getResponse().getStatusCode());
+ assertEquals("https://example.com",
exchange.getResponse().getHeaders().getLocation().toString());
+ }
}