diff --git a/pom.xml b/pom.xml
index 72b8c51f..be6e4b30 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,7 +15,7 @@
org.springframework.cloud
spring-cloud-build
- 2.1.4.BUILD-SNAPSHOT
+ 2.1.6.BUILD-SNAPSHOT
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
index 856800e8..b1221eca 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java
@@ -45,11 +45,13 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint;
import org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter;
+import org.springframework.cloud.gateway.filter.AlwaysRetainBodyGlobalFilter;
import org.springframework.cloud.gateway.filter.ForwardPathFilter;
import org.springframework.cloud.gateway.filter.ForwardRoutingFilter;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.NettyRoutingFilter;
import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter;
+import org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter;
import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter;
import org.springframework.cloud.gateway.filter.WebsocketRoutingFilter;
import org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter;
@@ -261,6 +263,16 @@ public class GatewayAutoConfiguration {
return new AdaptCachedBodyGlobalFilter();
}
+ @Bean
+ public AlwaysRetainBodyGlobalFilter alwaysRetainBodyGlobalFilter() {
+ return new AlwaysRetainBodyGlobalFilter();
+ }
+
+ @Bean
+ public RemoveCachedBodyFilter removeCachedBodyFilter() {
+ return new RemoveCachedBodyFilter();
+ }
+
@Bean
public RouteToRequestUrlFilter routeToRequestUrlFilter() {
return new RouteToRequestUrlFilter();
@@ -588,6 +600,9 @@ public class GatewayAutoConfiguration {
});
}
+ //TODO: add configuration to turn on wiretap
+ //httpClient = httpClient.wiretap(true);
+
return httpClient;
}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/event/EnableBodyCachingEvent.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/event/EnableBodyCachingEvent.java
new file mode 100644
index 00000000..c4c07563
--- /dev/null
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/event/EnableBodyCachingEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.gateway.event;
+
+import org.springframework.context.ApplicationEvent;
+
+public class EnableBodyCachingEvent extends ApplicationEvent {
+
+ private final String routeId;
+
+ public EnableBodyCachingEvent(Object source, String routeId) {
+ super(source);
+ this.routeId = routeId;
+ }
+
+ public String getRouteId() {
+ return this.routeId;
+ }
+
+}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/AlwaysRetainBodyGlobalFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/AlwaysRetainBodyGlobalFilter.java
new file mode 100644
index 00000000..d5d4f78c
--- /dev/null
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/AlwaysRetainBodyGlobalFilter.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2013-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.gateway.filter;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import org.springframework.cloud.gateway.event.EnableBodyCachingEvent;
+import org.springframework.cloud.gateway.route.Route;
+import org.springframework.context.ApplicationListener;
+import org.springframework.core.Ordered;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.core.io.buffer.NettyDataBuffer;
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
+import org.springframework.web.server.ServerWebExchange;
+
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
+
+public class AlwaysRetainBodyGlobalFilter
+ implements GlobalFilter, Ordered, ApplicationListener {
+
+ private static final Log log = LogFactory.getLog(AlwaysRetainBodyGlobalFilter.class);
+
+ private ConcurrentMap routesToCache = new ConcurrentHashMap<>();
+
+ /**
+ * Request body cache key.
+ */
+ public static final String ALWAYS_CACHE_REQUEST_BODY_KEY = "alwaysCacheRequestBody";
+
+ @Override
+ public void onApplicationEvent(EnableBodyCachingEvent event) {
+ this.routesToCache.putIfAbsent(event.getRouteId(), true);
+ }
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ Object body = exchange.getAttributeOrDefault(ALWAYS_CACHE_REQUEST_BODY_KEY, null);
+ Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
+
+ if (body != null || !this.routesToCache.containsKey(route.getId())) {
+ return chain.filter(exchange);
+ }
+
+ return DataBufferUtils.join(exchange.getRequest().getBody())
+ .flatMap(dataBuffer -> {
+ if (dataBuffer.readableByteCount() > 0) {
+ if (log.isTraceEnabled()) {
+ log.trace("retaining body in exchange attribute");
+ }
+ exchange.getAttributes().put(ALWAYS_CACHE_REQUEST_BODY_KEY,
+ dataBuffer);
+ }
+
+ ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
+ exchange.getRequest()) {
+ @Override
+ public Flux getBody() {
+ return Mono.fromSupplier(() -> {
+ if (exchange.getAttributeOrDefault(
+ ALWAYS_CACHE_REQUEST_BODY_KEY, null) == null) {
+ // probably == downstream closed
+ return null;
+ }
+ // TODO: deal with Netty
+ NettyDataBuffer pdb = (NettyDataBuffer) dataBuffer;
+ return pdb.factory()
+ .wrap(pdb.getNativeBuffer().retainedSlice());
+ }).flux();
+ }
+ };
+ return chain.filter(exchange.mutate().request(decorator).build());
+ }).switchIfEmpty(chain.filter(exchange));
+ }
+
+ @Override
+ public int getOrder() {
+ return -10;
+ }
+
+}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/RemoveCachedBodyFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/RemoveCachedBodyFilter.java
new file mode 100644
index 00000000..9411cb3d
--- /dev/null
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/RemoveCachedBodyFilter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.gateway.filter;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import reactor.core.publisher.Mono;
+
+import org.springframework.core.Ordered;
+import org.springframework.core.io.buffer.PooledDataBuffer;
+import org.springframework.web.server.ServerWebExchange;
+
+import static org.springframework.cloud.gateway.filter.AlwaysRetainBodyGlobalFilter.ALWAYS_CACHE_REQUEST_BODY_KEY;
+
+public class RemoveCachedBodyFilter implements GlobalFilter, Ordered {
+
+ private static final Log log = LogFactory.getLog(RemoveCachedBodyFilter.class);
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ return chain.filter(exchange).doFinally(s -> {
+ PooledDataBuffer b = (PooledDataBuffer) exchange.getAttributes()
+ .remove(ALWAYS_CACHE_REQUEST_BODY_KEY);
+ if (b != null && b.isAllocated()) {
+ if (log.isTraceEnabled()) {
+ log.trace("releasing cached body in exchange attribute");
+ }
+ b.release();
+ }
+ });
+ }
+
+ @Override
+ public int getOrder() {
+ return HIGHEST_PRECEDENCE;
+ }
+
+}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AbstractGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AbstractGatewayFilterFactory.java
index a4c63683..abeea4fa 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AbstractGatewayFilterFactory.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/AbstractGatewayFilterFactory.java
@@ -17,6 +17,8 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.cloud.gateway.support.AbstractConfigurable;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ApplicationEventPublisherAware;
/**
* This class is BETA and may be subject to change in a future release.
@@ -24,7 +26,9 @@ import org.springframework.cloud.gateway.support.AbstractConfigurable;
* @param {@link AbstractConfigurable} subtype
*/
public abstract class AbstractGatewayFilterFactory extends AbstractConfigurable
- implements GatewayFilterFactory {
+ implements GatewayFilterFactory, ApplicationEventPublisherAware {
+
+ private ApplicationEventPublisher publisher;
@SuppressWarnings("unchecked")
public AbstractGatewayFilterFactory() {
@@ -35,6 +39,15 @@ public abstract class AbstractGatewayFilterFactory extends AbstractConfigurab
super(configClass);
}
+ protected ApplicationEventPublisher getPublisher() {
+ return this.publisher;
+ }
+
+ @Override
+ public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
+ this.publisher = publisher;
+ }
+
public static class NameConfig {
private String name;
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/GatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/GatewayFilterFactory.java
index e8432dcb..2635f4e3 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/GatewayFilterFactory.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/GatewayFilterFactory.java
@@ -20,6 +20,7 @@ import java.util.function.Consumer;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.support.Configurable;
+import org.springframework.cloud.gateway.support.HasRouteId;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.cloud.gateway.support.ShortcutConfigurable;
import org.springframework.http.server.reactive.ServerHttpRequest;
@@ -41,6 +42,12 @@ public interface GatewayFilterFactory extends ShortcutConfigurable, Configura
String VALUE_KEY = "value";
// useful for javadsl
+ default GatewayFilter apply(String routeId, Consumer consumer) {
+ C config = newConfig();
+ consumer.accept(config);
+ return apply(routeId, config);
+ }
+
default GatewayFilter apply(Consumer consumer) {
C config = newConfig();
consumer.accept(config);
@@ -58,6 +65,14 @@ public interface GatewayFilterFactory extends ShortcutConfigurable, Configura
GatewayFilter apply(C config);
+ default GatewayFilter apply(String routeId, C config) {
+ if (config instanceof HasRouteId) {
+ HasRouteId hasRouteId = (HasRouteId) config;
+ hasRouteId.setRouteId(routeId);
+ }
+ return apply(config);
+ }
+
default String name() {
// TODO: deal with proxys
return NameUtils.normalizeFilterFactoryName(getClass());
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java
index c4688538..db20c193 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/HystrixGatewayFilterFactory.java
@@ -86,6 +86,8 @@ public class HystrixGatewayFilterFactory
return singletonList(NAME_KEY);
}
+ @Override
+ // TODO: make Config implement HasRouteId and remove this method.
public GatewayFilter apply(String routeId, Consumer consumer) {
Config config = newConfig();
consumer.accept(config);
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactory.java
index 70292873..d3d5cb72 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactory.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactory.java
@@ -66,9 +66,11 @@ public class RequestSizeGatewayFilterFactory extends
Long currentRequestSize = Long.valueOf(contentLength);
if (currentRequestSize > requestSizeConfig.getMaxSize()) {
exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
- exchange.getResponse().getHeaders().add("errorMessage",
- getErrorMessage(currentRequestSize,
- requestSizeConfig.getMaxSize()));
+ if (!exchange.getResponse().isCommitted()) {
+ exchange.getResponse().getHeaders().add("errorMessage",
+ getErrorMessage(currentRequestSize,
+ requestSizeConfig.getMaxSize()));
+ }
return exchange.getResponse().setComplete();
}
}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java
index 8115e41a..0c7096fe 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactory.java
@@ -33,7 +33,9 @@ import reactor.retry.RepeatContext;
import reactor.retry.Retry;
import reactor.retry.RetryContext;
+import org.springframework.cloud.gateway.event.EnableBodyCachingEvent;
import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.support.HasRouteId;
import org.springframework.cloud.gateway.support.TimeoutException;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
@@ -130,7 +132,7 @@ public class RetryGatewayFilterFactory
.retryMax(retryConfig.getRetries());
}
- return apply(statusCodeRepeat, exceptionRetry);
+ return apply(retryConfig.getRouteId(), statusCodeRepeat, exceptionRetry);
}
public boolean exceedsMaxIterations(ServerWebExchange exchange,
@@ -145,7 +147,7 @@ public class RetryGatewayFilterFactory
}
public void reset(ServerWebExchange exchange) {
- // TODO: what else to do to reset SWE?
+ // TODO: what else to do to reset exchange?
Set addedHeaders = exchange.getAttributeOrDefault(
CLIENT_RESPONSE_HEADER_NAMES, Collections.emptySet());
addedHeaders
@@ -153,8 +155,18 @@ public class RetryGatewayFilterFactory
exchange.getAttributes().remove(GATEWAY_ALREADY_ROUTED_ATTR);
}
+ @Deprecated
public GatewayFilter apply(Repeat repeat,
Retry retry) {
+ return apply(null, repeat, retry);
+ }
+
+ public GatewayFilter apply(String routeId, Repeat repeat,
+ Retry retry) {
+ if (routeId != null && getPublisher() != null) {
+ // send an event to enable caching
+ getPublisher().publishEvent(new EnableBodyCachingEvent(this, routeId));
+ }
return (exchange, chain) -> {
trace("Entering retry-filter");
@@ -193,7 +205,9 @@ public class RetryGatewayFilterFactory
}
@SuppressWarnings("unchecked")
- public static class RetryConfig {
+ public static class RetryConfig implements HasRouteId {
+
+ private String routeId;
private int retries = 3;
@@ -219,6 +233,16 @@ public class RetryGatewayFilterFactory
Assert.notEmpty(this.methods, "methods may not be empty");
}
+ @Override
+ public void setRouteId(String routeId) {
+ this.routeId = routeId;
+ }
+
+ @Override
+ public String getRouteId() {
+ return this.routeId;
+ }
+
public int getRetries() {
return retries;
}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java
index 3b6d26e0..5f8b2400 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/RouteDefinitionRouteLocator.java
@@ -147,7 +147,7 @@ public class RouteDefinitionRouteLocator
.replaceFilters(gatewayFilters).build();
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({ "Duplicates", "unchecked" })
private List loadGatewayFilters(String id,
List filterDefinitions) {
List filters = filterDefinitions.stream().map(definition -> {
@@ -173,7 +173,7 @@ public class RouteDefinitionRouteLocator
factory.shortcutFieldPrefix(), definition.getName(), validator,
conversionService);
- GatewayFilter gatewayFilter = factory.apply(configuration);
+ GatewayFilter gatewayFilter = factory.apply(id, configuration);
if (this.publisher != null) {
this.publisher.publishEvent(new FilterArgsEvent(this, id, properties));
}
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java
index 3a72b1aa..1fa2093f 100644
--- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java
@@ -474,8 +474,9 @@ public class GatewayFilterSpec extends UriSpec {
* @return a {@link GatewayFilterSpec} that can be used to apply additional filters
*/
public GatewayFilterSpec retry(int retries) {
- return filter(getBean(RetryGatewayFilterFactory.class)
- .apply(retryConfig -> retryConfig.setRetries(retries)));
+ return filter(
+ getBean(RetryGatewayFilterFactory.class).apply(this.routeBuilder.getId(),
+ retryConfig -> retryConfig.setRetries(retries)));
}
/**
@@ -487,7 +488,8 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec retry(
Consumer retryConsumer) {
- return filter(getBean(RetryGatewayFilterFactory.class).apply(retryConsumer));
+ return filter(getBean(RetryGatewayFilterFactory.class)
+ .apply(this.routeBuilder.getId(), retryConsumer));
}
/**
@@ -498,7 +500,9 @@ public class GatewayFilterSpec extends UriSpec {
*/
public GatewayFilterSpec retry(Repeat repeat,
Retry retry) {
- return filter(getBean(RetryGatewayFilterFactory.class).apply(repeat, retry));
+ RetryGatewayFilterFactory filterFactory = getBean(
+ RetryGatewayFilterFactory.class);
+ return filter(filterFactory.apply(this.routeBuilder.getId(), repeat, retry));
}
/**
diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/HasRouteId.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/HasRouteId.java
new file mode 100644
index 00000000..a9db1637
--- /dev/null
+++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/HasRouteId.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013-2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.gateway.support;
+
+public interface HasRouteId {
+
+ void setRouteId(String routeId);
+
+ String getRouteId();
+
+}
diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java
index e0459e28..9df89ac2 100644
--- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java
+++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java
@@ -37,7 +37,8 @@ public class GatewayAutoConfigurationTests {
@Test
public void noHiddenHttpMethodFilter() {
try (ConfigurableApplicationContext ctx = SpringApplication.run(
- NoHiddenHttpMethodFilterConfig.class, "--spring.jmx.enabled=false")) {
+ NoHiddenHttpMethodFilterConfig.class, "--spring.jmx.enabled=false",
+ "--server.port=0")) {
assertThat(ctx.getEnvironment()
.getProperty("spring.webflux.hiddenmethod.filter.enabled"))
.isEqualTo("false");
diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactoryTest.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactoryTest.java
index 011ea152..dc8b460c 100644
--- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactoryTest.java
+++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RequestSizeGatewayFilterFactoryTest.java
@@ -43,14 +43,14 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@DirtiesContext
public class RequestSizeGatewayFilterFactoryTest extends BaseWebClientTests {
- private static final String responseMesssage = "Request size is larger than permissible limit. Request size is 6.0 MB "
- + "where permissible limit is 5.0 MB";
+ private static final String responseMesssage = "Request size is larger than permissible limit. Request size is . . "
+ + "where permissible limit is .*";
@Test
public void setRequestSizeFilterWorks() {
- testClient.get().uri("/headers").header("Host", "www.setrequestsize.org")
- .header("content-length", "6000000").exchange().expectStatus()
- .isEqualTo(HttpStatus.PAYLOAD_TOO_LARGE).expectHeader()
+ testClient.post().uri("/post").header("Host", "www.setrequestsize.org")
+ .header("content-length", "6").syncBody("123456").exchange()
+ .expectStatus().isEqualTo(HttpStatus.PAYLOAD_TOO_LARGE).expectHeader()
.valueMatches("errorMessage", responseMesssage);
}
@@ -67,7 +67,7 @@ public class RequestSizeGatewayFilterFactoryTest extends BaseWebClientTests {
return builder.routes()
.route("test_request_size",
r -> r.order(-1).host("**.setrequestsize.org")
- .filters(f -> f.setRequestSize(5000000L)).uri(uri))
+ .filters(f -> f.setRequestSize(5L)).uri(uri))
.build();
}
diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java
index 70003dee..7cfa6f4d 100644
--- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java
+++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory/RetryGatewayFilterFactoryIntegrationTests.java
@@ -40,6 +40,7 @@ import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
@@ -79,11 +80,10 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest
}
@Test
- // TODO: support post
public void retryFilterPost() {
- testClient.post().uri("/retry?key=post").exchange().expectStatus()
- .is5xxServerError();
- // .expectBody(String.class).isEqualTo("3");
+ testClient.post().uri("/retry?key=post")
+ .header(HttpHeaders.HOST, "www.retryjava.org").syncBody("Hello")
+ .exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("3");
}
@Test
@@ -145,7 +145,8 @@ public class RetryGatewayFilterFactoryIntegrationTests extends BaseWebClientTest
return builder.routes()
.route("retry_java", r -> r.host("**.retryjava.org")
.filters(f -> f.prefixPath("/httpbin")
- .retry(config -> config.setRetries(2)))
+ .retry(config -> config.setRetries(2)
+ .setMethods(HttpMethod.POST, HttpMethod.GET)))
.uri(uri))
.route("retry_with_loadbalancer",
r -> r.host("**.retrywithloadbalancer.org")
diff --git a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/FormIntegrationTests.java b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/FormIntegrationTests.java
index fee866e9..fbbc20c7 100644
--- a/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/FormIntegrationTests.java
+++ b/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/test/FormIntegrationTests.java
@@ -21,17 +21,18 @@ import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.context.annotation.Import;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
@@ -42,7 +43,6 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
import static org.springframework.cloud.gateway.test.TestUtils.getMap;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED;
-import static org.springframework.web.reactive.function.BodyExtractors.toMono;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
@@ -73,6 +73,8 @@ public class FormIntegrationTests extends BaseWebClientTests {
public void multipartFormDataWorks() {
ClassPathResource img = new ClassPathResource("1x1.png");
+ TestRestTemplate rest = new TestRestTemplate();
+
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
@@ -81,17 +83,14 @@ public class FormIntegrationTests extends BaseWebClientTests {
MultiValueMap parts = new LinkedMultiValueMap<>();
parts.add("imgpart", entity);
- Mono