fix post request with body processed twice in retry filter https://github.com/spring-cloud/spring-cloud-gateway/issues/1315

This commit is contained in:
Nikita Konev
2019-10-01 01:51:01 +03:00
committed by Spencer Gibb
parent 0d2b87af30
commit e285b841de
3 changed files with 43 additions and 4 deletions

View File

@@ -70,11 +70,18 @@ public class AdaptCachedBodyGlobalFilter
return chain.filter(exchange);
}
final Mono<String> requestProcessingFinishedFlag = Mono
.just("requestProcessingFinishedFlag");
return ServerWebExchangeUtils
.cacheRequestBody(exchange,
(serverHttpRequest) -> chain.filter(
exchange.mutate().request(serverHttpRequest).build()))
.switchIfEmpty(chain.filter(exchange));
.cacheRequestBody(exchange, (serverHttpRequest) -> chain
.filter(exchange.mutate().request(serverHttpRequest).build())
// suppress empty mono response from FilteringWebHandler, see
// https://github.com/spring-cloud/spring-cloud-gateway/issues/1315
.then(requestProcessingFinishedFlag))
// when request body is empty - we return from cacheRequestBody() with
// empty mono - so we will process that request
.switchIfEmpty(chain.filter(exchange).then(requestProcessingFinishedFlag))
.then();
}
@Override

View File

@@ -27,6 +27,8 @@ import com.netflix.loadbalancer.ServerList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,6 +36,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory.RetryConfig;
@@ -49,6 +52,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -63,8 +67,20 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
"spring.cloud.gateway.httpclient.connect-timeout=500",
"spring.cloud.gateway.httpclient.response-timeout=2s" })
@DirtiesContext
// default filter AddResponseHeader suppresses bug
// https://github.com/spring-cloud/spring-cloud-gateway/issues/1315,
// so we use only PrefixPath filter
@ActiveProfiles("only-prefix-filter")
public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTests {
@Rule
public final OutputCapture capture = new OutputCapture();
@Before
public void before() {
capture.reset();
}
@Test
public void retryFilterGet() {
testClient.get().uri("/retry?key=get").exchange().expectStatus().isOk()
@@ -115,6 +131,17 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest
.exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("3");
}
@Test
public void retryFilterPostOneTime() {
testClient.post().uri(
"/retrypost?key=retryFilterPostOneTime&expectedbody=HelloGateway&count=1")
.header(HttpHeaders.HOST, "www.retrypostconfig.org")
.syncBody("HelloGateway").exchange().expectStatus().isOk();
assertThat(this.capture.toString()).contains("setting new iteration in attr 0");
assertThat(this.capture.toString())
.doesNotContain("setting new iteration in attr 1");
}
@Test
public void retriesSleepyRequest() throws Exception {
testClient.mutate().responseTimeout(Duration.ofSeconds(10)).build().get()

View File

@@ -0,0 +1,5 @@
spring:
cloud:
gateway:
default-filters:
- PrefixPath=/httpbin