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());
+    }
 }

Reply via email to