Bumping versions

This commit is contained in:
buildmaster
2024-07-23 12:11:58 +00:00
parent 4a2c6d836f
commit 656ab5aba4
292 changed files with 5555 additions and 3015 deletions

View File

@@ -107,7 +107,7 @@ public class GRPCApplication {
public void hello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
if ("failWithRuntimeException!".equals(request.getFirstName())) {
StatusRuntimeException exception = Status.FAILED_PRECONDITION.withDescription("Invalid firstName")
.asRuntimeException();
.asRuntimeException();
responseObserver.onError(exception);
responseObserver.onCompleted();
return;

View File

@@ -59,7 +59,7 @@ public class GRPCApplicationTests {
ManagedChannel channel = createSecuredChannel(gatewayPort);
final HelloResponse response = HelloServiceGrpc.newBlockingStub(channel)
.hello(HelloRequest.newBuilder().setFirstName("Sir").setLastName("FromClient").build());
.hello(HelloRequest.newBuilder().setFirstName("Sir").setLastName("FromClient").build());
Assertions.assertThat(response.getGreeting()).isEqualTo("Hello, Sir FromClient");
}
@@ -67,9 +67,11 @@ public class GRPCApplicationTests {
private ManagedChannel createSecuredChannel(int port) throws SSLException {
TrustManager[] trustAllCerts = createTrustAllTrustManager();
return NettyChannelBuilder.forAddress("localhost", port).useTransportSecurity()
.sslContext(GrpcSslContexts.forClient().trustManager(trustAllCerts[0]).build()).negotiationType(TLS)
.build();
return NettyChannelBuilder.forAddress("localhost", port)
.useTransportSecurity()
.sslContext(GrpcSslContexts.forClient().trustManager(trustAllCerts[0]).build())
.negotiationType(TLS)
.build();
}
@Test
@@ -78,7 +80,7 @@ public class GRPCApplicationTests {
try {
HelloServiceGrpc.newBlockingStub(channel)
.hello(HelloRequest.newBuilder().setFirstName("failWithRuntimeException!").build());
.hello(HelloRequest.newBuilder().setFirstName("failWithRuntimeException!").build());
}
catch (StatusRuntimeException e) {
Assertions.assertThat(FAILED_PRECONDITION.getCode()).isEqualTo(e.getStatus().getCode());

View File

@@ -74,8 +74,10 @@ public class JsonToGrpcApplicationTests {
configurer.addRoute(grpcServerPort, "/json/hello",
"JsonToGrpc=file:src/main/proto/hello.pb,file:src/main/proto/hello.proto,HelloService,hello");
String response = restTemplate.postForEntity("https://localhost:" + this.gatewayPort + "/json/hello",
"{\"firstName\":\"Duff\", \"lastName\":\"McKagan\"}", String.class).getBody();
String response = restTemplate
.postForEntity("https://localhost:" + this.gatewayPort + "/json/hello",
"{\"firstName\":\"Duff\", \"lastName\":\"McKagan\"}", String.class)
.getBody();
Assertions.assertThat(response).isNotNull();
Assertions.assertThat(response).contains("{\"greeting\":\"Hello, Duff McKagan\"}");
@@ -94,7 +96,9 @@ public class JsonToGrpcApplicationTests {
NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", sslSocketFactory).register("http", new PlainConnectionSocketFactory()).build();
.register("https", sslSocketFactory)
.register("http", new PlainConnectionSocketFactory())
.build();
HttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(socketFactoryRegistry);
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();

View File

@@ -101,7 +101,9 @@ public class RouteConfigurer {
NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", sslSocketFactory).register("http", new PlainConnectionSocketFactory()).build();
.register("https", sslSocketFactory)
.register("http", new PlainConnectionSocketFactory())
.build();
HttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(socketFactoryRegistry);
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();

View File

@@ -54,10 +54,12 @@ public class Http2Application {
@Bean
public RouteLocator myRouteLocator(RouteLocatorBuilder builder) {
return builder.routes().route(r -> r.path("/myprefix/**").filters(f -> f.stripPrefix(1)).uri("lb://myservice"))
.route(r -> r.path("/nossl/**").filters(f -> f.stripPrefix(1)).uri("lb://nossl"))
.route(r -> r.path("/neverssl/**").filters(f -> f.stripPrefix(1)).uri("http://neverssl.com"))
.route(r -> r.path("/httpbin/**").uri("https://nghttp2.org")).build();
return builder.routes()
.route(r -> r.path("/myprefix/**").filters(f -> f.stripPrefix(1)).uri("lb://myservice"))
.route(r -> r.path("/nossl/**").filters(f -> f.stripPrefix(1)).uri("lb://nossl"))
.route(r -> r.path("/neverssl/**").filters(f -> f.stripPrefix(1)).uri("http://neverssl.com"))
.route(r -> r.path("/httpbin/**").uri("https://nghttp2.org"))
.build();
}
public static void main(String[] args) {

View File

@@ -74,13 +74,17 @@ public class Http2ApplicationTests {
static HttpClient getHttpClient() {
return HttpClient
.create(ConnectionProvider.builder("test").maxConnections(100)
.pendingAcquireTimeout(Duration.ofMillis(0)).pendingAcquireMaxCount(-1).build())
.protocol(HttpProtocol.HTTP11, HttpProtocol.H2).secure(sslContextSpec -> {
Http2SslContextSpec clientSslCtxt = Http2SslContextSpec.forClient()
.configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE));
sslContextSpec.sslContext(clientSslCtxt);
});
.create(ConnectionProvider.builder("test")
.maxConnections(100)
.pendingAcquireTimeout(Duration.ofMillis(0))
.pendingAcquireMaxCount(-1)
.build())
.protocol(HttpProtocol.HTTP11, HttpProtocol.H2)
.secure(sslContextSpec -> {
Http2SslContextSpec clientSslCtxt = Http2SslContextSpec.forClient()
.configure(builder -> builder.trustManager(InsecureTrustManagerFactory.INSTANCE));
sslContextSpec.sslContext(clientSslCtxt);
});
}
}

View File

@@ -64,7 +64,9 @@ public class NosslTests {
System.err.println("nossl.port = " + nosslPort);
Hooks.onOperatorDebug();
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(NosslConfiguration.class)
.properties("server.port=" + nosslPort).profiles("nossl").run()) {
.properties("server.port=" + nosslPort)
.profiles("nossl")
.run()) {
String uri = "https://localhost:" + port + "/nossl";
String expected = "nossl";
assertResponse(uri, expected);

View File

@@ -47,8 +47,9 @@ public class MvcFailureAnalyzerApplication {
@Bean
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public RouteLocator myRouteLocator(RouteLocatorBuilder builder) {
return builder.routes().route(r -> r.path("/myprefix/**").filters(f -> f.stripPrefix(1)).uri("lb://myservice"))
.build();
return builder.routes()
.route(r -> r.path("/myprefix/**").filters(f -> f.stripPrefix(1)).uri("lb://myservice"))
.build();
}
}

View File

@@ -40,7 +40,7 @@ public class MvcFailureAnalyzerApplicationTests {
@Test
public void exceptionThrown(CapturedOutput output) {
assertThatThrownBy(() -> new SpringApplication(MvcFailureAnalyzerApplication.class).run("--server.port=0"))
.hasRootCauseInstanceOf(MvcFoundOnClasspathException.class);
.hasRootCauseInstanceOf(MvcFoundOnClasspathException.class);
assertThat(output).contains(MvcFoundOnClasspathFailureAnalyzer.MESSAGE,
MvcFoundOnClasspathFailureAnalyzer.ACTION);
}
@@ -48,7 +48,7 @@ public class MvcFailureAnalyzerApplicationTests {
@Test
public void exceptionNotThrownWhenDisabled(CapturedOutput output) {
assertThatCode(() -> new SpringApplication(MvcFailureAnalyzerApplication.class)
.run("--spring.cloud.gateway.enabled=false", "--server.port=0")).doesNotThrowAnyException();
.run("--spring.cloud.gateway.enabled=false", "--server.port=0")).doesNotThrowAnyException();
assertThat(output).doesNotContain(MvcFoundOnClasspathFailureAnalyzer.MESSAGE,
MvcFoundOnClasspathFailureAnalyzer.ACTION);
}
@@ -57,11 +57,16 @@ public class MvcFailureAnalyzerApplicationTests {
public void exceptionNotThrownWhenReactiveTypeSet(CapturedOutput output) {
assertThatCode(() -> {
ConfigurableApplicationContext context = new SpringApplication(MvcFailureAnalyzerApplication.class)
.run("--spring.main.web-application-type=reactive", "--server.port=0", "--debug=true");
.run("--spring.main.web-application-type=reactive", "--server.port=0", "--debug=true");
Integer port = context.getEnvironment().getProperty("local.server.port", Integer.class);
WebTestClient client = WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build();
client.get().uri("/myprefix/hello").exchange().expectStatus().isOk().expectBody(String.class)
.isEqualTo("Hello");
client.get()
.uri("/myprefix/hello")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("Hello");
context.close();
}).doesNotThrowAnyException();
assertThat(output).doesNotContain(MvcFoundOnClasspathFailureAnalyzer.MESSAGE,

View File

@@ -280,8 +280,8 @@ public class ProxyExchange<T> {
HttpServletRequest request = this.webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = this.webRequest.getNativeResponse(HttpServletResponse.class);
try {
request.getRequestDispatcher(path).forward(new BodyForwardingHttpServletRequest(request, response),
response);
request.getRequestDispatcher(path)
.forward(new BodyForwardingHttpServletRequest(request, response), response);
}
catch (Exception e) {
throw new IllegalStateException("Cannot forward request", e);
@@ -363,8 +363,9 @@ public class ProxyExchange<T> {
ArrayList<String> headerNames = new ArrayList<>();
webRequest.getHeaderNames().forEachRemaining(headerNames::add);
Set<String> filteredKeys = filterHeaderKeys(headerNames);
filteredKeys.stream().filter(key -> !headers.containsKey(key))
.forEach(header -> headers.addAll(header, Arrays.asList(webRequest.getHeaderValues(header))));
filteredKeys.stream()
.filter(key -> !headers.containsKey(key))
.forEach(header -> headers.addAll(header, Arrays.asList(webRequest.getHeaderValues(header))));
}
private BodyBuilder headers(BodyBuilder builder) {
@@ -382,8 +383,9 @@ public class ProxyExchange<T> {
private Set<String> filterHeaderKeys(Collection<String> headerNames) {
final Set<String> excludedHeaders = this.excluded != null ? this.excluded : Collections.emptySet();
return headerNames.stream().filter(header -> !excludedHeaders.contains(header.toLowerCase()))
.collect(Collectors.toSet());
return headerNames.stream()
.filter(header -> !excludedHeaders.contains(header.toLowerCase()))
.collect(Collectors.toSet());
}
private void proxy() {

View File

@@ -109,7 +109,7 @@ public class ProductionConfigurationTests {
@Test
public void post() {
assertThat(rest.postForObject("/proxy/0", Collections.singletonMap("name", "foo"), Bar.class).getName())
.isEqualTo("host=localhost:" + port + ";foo");
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
@@ -124,7 +124,7 @@ public class ProductionConfigurationTests {
headers.setContentLength(json.length());
var request = new HttpEntity<>(json, headers);
assertThat(rest.postForEntity("/proxy/checkContentLength", request, Void.class).getStatusCode())
.isEqualTo(HttpStatus.OK);
.isEqualTo(HttpStatus.OK);
}
@Test
@@ -143,7 +143,7 @@ public class ProductionConfigurationTests {
public void postForwardHeader() {
ResponseEntity<List<Bar>> result = rest.exchange(
RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/forward/special/bars"))
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))),
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))),
new ParameterizedTypeReference<List<Bar>>() {
});
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
@@ -153,20 +153,17 @@ public class ProductionConfigurationTests {
@Test
public void postForwardBody() {
ResponseEntity<String> result = rest
.exchange(
RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/forward/body/bars"))
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))),
String.class);
.exchange(RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/forward/body/bars"))
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))), String.class);
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(result.getBody()).contains("foo");
}
@Test
public void postForwardForgetBody() {
ResponseEntity<String> result = rest.exchange(
RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/forward/forget/bars"))
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))),
String.class);
ResponseEntity<String> result = rest
.exchange(RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/forward/forget/bars"))
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))), String.class);
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(result.getBody()).contains("foo");
}
@@ -175,7 +172,7 @@ public class ProductionConfigurationTests {
public void postForwardBodyFoo() {
ResponseEntity<List<Bar>> result = rest.exchange(
RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/forward/body/bars"))
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))),
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))),
new ParameterizedTypeReference<List<Bar>>() {
});
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
@@ -186,44 +183,62 @@ public class ProductionConfigurationTests {
public void list() {
assertThat(rest.exchange(
RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy"))
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))),
.body(Collections.singletonList(Collections.singletonMap("name", "foo"))),
new ParameterizedTypeReference<List<Bar>>() {
}).getBody().iterator().next().getName()).isEqualTo("host=localhost:" + port + ";foo");
})
.getBody()
.iterator()
.next()
.getName()).isEqualTo("host=localhost:" + port + ";foo");
}
@Test
public void bodyless() {
assertThat(rest.postForObject("/proxy/0", Collections.singletonMap("name", "foo"), Bar.class).getName())
.isEqualTo("host=localhost:" + port + ";foo");
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
public void entity() {
assertThat(
rest.exchange(RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/entity"))
.body(Collections.singletonMap("name", "foo")), new ParameterizedTypeReference<List<Bar>>() {
}).getBody().iterator().next().getName()).isEqualTo("host=localhost:" + port + ";foo");
rest.exchange(
RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/entity"))
.body(Collections.singletonMap("name", "foo")),
new ParameterizedTypeReference<List<Bar>>() {
})
.getBody()
.iterator()
.next()
.getName())
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
public void entityWithType() {
assertThat(
rest.exchange(RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/type"))
.body(Collections.singletonMap("name", "foo")), new ParameterizedTypeReference<List<Bar>>() {
}).getBody().iterator().next().getName()).isEqualTo("host=localhost:" + port + ";foo");
rest.exchange(
RequestEntity.post(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/type"))
.body(Collections.singletonMap("name", "foo")),
new ParameterizedTypeReference<List<Bar>>() {
})
.getBody()
.iterator()
.next()
.getName())
.isEqualTo("host=localhost:" + port + ";foo");
}
@Test
public void single() {
assertThat(rest.postForObject("/proxy/single", Collections.singletonMap("name", "foobar"), Bar.class).getName())
.isEqualTo("host=localhost:" + port + ";foobar");
.isEqualTo("host=localhost:" + port + ";foobar");
}
@Test
public void converter() {
assertThat(
rest.postForObject("/proxy/converter", Collections.singletonMap("name", "foobar"), Bar.class).getName())
.isEqualTo("host=localhost:" + port + ";foobar");
.isEqualTo("host=localhost:" + port + ";foobar");
}
@Test
@@ -254,8 +269,11 @@ public class ProductionConfigurationTests {
@SuppressWarnings({ "Duplicates", "unchecked" })
public void testSensitiveHeadersOverride() {
RequestEntity<Void> request = RequestEntity
.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/headers")).header("foo", "bar")
.header("abc", "xyz").header("cookie", "monster").build();
.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/headers"))
.header("foo", "bar")
.header("abc", "xyz")
.header("cookie", "monster")
.build();
Map<String, List<String>> headers = rest.exchange(request, Map.class).getBody();
assertThat(headers).doesNotContainKey("foo").doesNotContainKey("hello").containsKeys("bar", "abc");
@@ -265,9 +283,12 @@ public class ProductionConfigurationTests {
@Test
@SuppressWarnings({ "Duplicates", "unchecked" })
public void testSensitiveHeadersDefault() {
Map<String, List<String>> headers = rest.exchange(RequestEntity
Map<String, List<String>> headers = rest
.exchange(RequestEntity
.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/sensitive-headers-default"))
.header("cookie", "monster").build(), Map.class).getBody();
.header("cookie", "monster")
.build(), Map.class)
.getBody();
assertThat(headers).doesNotContainKey("cookie");
}
@@ -276,9 +297,12 @@ public class ProductionConfigurationTests {
@SuppressWarnings({ "Duplicates", "unchecked" })
public void headers() {
Map<String, List<String>> headers = rest
.exchange(RequestEntity.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/headers"))
.header("foo", "bar").header("abc", "xyz").header("baz", "fob").build(), Map.class)
.getBody();
.exchange(RequestEntity.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/headers"))
.header("foo", "bar")
.header("abc", "xyz")
.header("baz", "fob")
.build(), Map.class)
.getBody();
assertThat(headers).doesNotContainKey("foo").doesNotContainKey("hello").containsKeys("bar", "abc");
assertThat(headers.get("bar")).containsOnly("hello");
@@ -289,9 +313,10 @@ public class ProductionConfigurationTests {
@Test
public void forwardedHeaderUsesHost() {
Map<String, List<String>> headers = rest
.exchange(RequestEntity.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/headers"))
.header("host", "foo:1234").build(), Map.class)
.getBody();
.exchange(RequestEntity.get(rest.getRestTemplate().getUriTemplateHandler().expand("/proxy/headers"))
.header("host", "foo:1234")
.build(), Map.class)
.getBody();
assertThat(headers).containsKey("forwarded");
assertThat(headers.get("forwarded").size()).isEqualTo(1);
@@ -381,9 +406,11 @@ public class ProductionConfigurationTests {
@PostMapping("/proxy/converter")
public ResponseEntity<Bar> implicitEntityWithConverter(@RequestBody Foo foo,
ProxyExchange<List<Bar>> proxy) {
return proxy.uri(home.toString() + "/bars").body(Arrays.asList(foo))
.post(response -> ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders())
.body(response.getBody().iterator().next()));
return proxy.uri(home.toString() + "/bars")
.body(Arrays.asList(foo))
.post(response -> ResponseEntity.status(response.getStatusCode())
.headers(response.getHeaders())
.body(response.getBody().iterator().next()));
}
@PostMapping("/proxy/no-body")
@@ -399,8 +426,11 @@ public class ProductionConfigurationTests {
@DeleteMapping("/proxy/{id}")
public ResponseEntity<?> deleteWithBody(@PathVariable Integer id, @RequestBody Foo foo,
ProxyExchange<?> proxy) {
return proxy.uri(home.toString() + "/foos/" + id).body(foo).delete(response -> ResponseEntity
.status(response.getStatusCode()).headers(response.getHeaders()).body(response.getBody()));
return proxy.uri(home.toString() + "/foos/" + id)
.body(foo)
.delete(response -> ResponseEntity.status(response.getStatusCode())
.headers(response.getHeaders())
.body(response.getBody()));
}
@GetMapping("/forward/**")
@@ -461,8 +491,9 @@ public class ProductionConfigurationTests {
}
private <T> ResponseEntity<T> first(ResponseEntity<List<T>> response) {
return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders())
.body(response.getBody().iterator().next());
return ResponseEntity.status(response.getStatusCode())
.headers(response.getHeaders())
.body(response.getBody().iterator().next());
}
}

View File

@@ -165,8 +165,9 @@ public class GatewaySampleApplication {
@Bean
public RouterFunction<ServerResponse> testWhenMetricPathIsNotMeet() {
RouterFunction<ServerResponse> route = RouterFunctions.route(
RequestPredicates.path("/actuator/metrics/spring.cloud.gateway.requests"), request -> ServerResponse
.ok().body(BodyInserters.fromValue(HELLO_FROM_FAKE_ACTUATOR_METRICS_GATEWAY_REQUESTS)));
RequestPredicates.path("/actuator/metrics/spring.cloud.gateway.requests"),
request -> ServerResponse.ok()
.body(BodyInserters.fromValue(HELLO_FROM_FAKE_ACTUATOR_METRICS_GATEWAY_REQUESTS)));
return route;
}

View File

@@ -52,8 +52,10 @@ public class ThrottleGatewayFilter implements GatewayFilter {
}
synchronized (this) {
if (tokenBucket == null) {
tokenBucket = TokenBuckets.builder().withCapacity(capacity)
.withFixedIntervalRefillStrategy(refillTokens, refillPeriod, refillUnit).build();
tokenBucket = TokenBuckets.builder()
.withCapacity(capacity)
.withFixedIntervalRefillStrategy(refillTokens, refillPeriod, refillUnit)
.build();
}
}
return tokenBucket;

View File

@@ -92,100 +92,171 @@ public class GatewaySampleApplicationTests {
@Test
@SuppressWarnings("unchecked")
public void readBodyPredicateStringWorks() {
webClient.post().uri("/post").header("Host", "www.readbody.org").bodyValue("hi").exchange().expectStatus()
.isOk().expectHeader().valueEquals("X-TestHeader", "read_body_pred").expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("data", "hi"));
webClient.post()
.uri("/post")
.header("Host", "www.readbody.org")
.bodyValue("hi")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-TestHeader", "read_body_pred")
.expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("data", "hi"));
}
@Test
@SuppressWarnings("unchecked")
public void rewriteRequestBodyStringWorks() {
webClient.post().uri("/post").header("Host", "www.rewriterequestupper.org").bodyValue("hello").exchange()
.expectStatus().isOk().expectHeader().valueEquals("X-TestHeader", "rewrite_request_upper")
.expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("data", "HELLOHELLO"));
webClient.post()
.uri("/post")
.header("Host", "www.rewriterequestupper.org")
.bodyValue("hello")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-TestHeader", "rewrite_request_upper")
.expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("data", "HELLOHELLO"));
}
@Test
@SuppressWarnings("unchecked")
public void rewriteRequestBodyObjectWorks() {
webClient.post().uri("/post").header("Host", "www.rewriterequestobj.org").bodyValue("hello").exchange()
.expectStatus().isOk().expectHeader().valueEquals("X-TestHeader", "rewrite_request")
.expectBody(Map.class).consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("data",
"{\"message\":\"HELLO\"}"));
webClient.post()
.uri("/post")
.header("Host", "www.rewriterequestobj.org")
.bodyValue("hello")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-TestHeader", "rewrite_request")
.expectBody(Map.class)
.consumeWith(
result -> assertThat(result.getResponseBody()).containsEntry("data", "{\"message\":\"HELLO\"}"));
}
@Test
@SuppressWarnings("unchecked")
public void rewriteResponseBodyStringWorks() {
webClient.post().uri("/post").header("Host", "www.rewriteresponseupper.org").bodyValue("hello").exchange()
.expectStatus().isOk().expectHeader().valueEquals("X-TestHeader", "rewrite_response_upper")
.expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("DATA", "HELLO"));
webClient.post()
.uri("/post")
.header("Host", "www.rewriteresponseupper.org")
.bodyValue("hello")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-TestHeader", "rewrite_response_upper")
.expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("DATA", "HELLO"));
}
@Test
@SuppressWarnings("unchecked")
public void rewriteResponseEmptyBodyToStringWorks() {
webClient.post().uri("/post/empty").header("Host", "www.rewriteemptyresponse.org").exchange().expectStatus()
.isOk().expectHeader().valueEquals("X-TestHeader", "rewrite_empty_response").expectBody(String.class)
.consumeWith(result -> assertThat(result.getResponseBody()).isEqualTo("emptybody"));
webClient.post()
.uri("/post/empty")
.header("Host", "www.rewriteemptyresponse.org")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-TestHeader", "rewrite_empty_response")
.expectBody(String.class)
.consumeWith(result -> assertThat(result.getResponseBody()).isEqualTo("emptybody"));
}
@Test
@SuppressWarnings("unchecked")
public void emptyBodySupplierNotCalledWhenBodyPresent() {
webClient.post().uri("/post").header("Host", "www.rewriteresponsewithfailsupplier.org").bodyValue("hello")
.exchange().expectStatus().isOk().expectHeader()
.valueEquals("X-TestHeader", "rewrite_response_fail_supplier").expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("DATA", "HELLO"));
webClient.post()
.uri("/post")
.header("Host", "www.rewriteresponsewithfailsupplier.org")
.bodyValue("hello")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-TestHeader", "rewrite_response_fail_supplier")
.expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("DATA", "HELLO"));
}
@Test
@SuppressWarnings("unchecked")
public void rewriteResponeBodyObjectWorks() {
webClient.post().uri("/post").header("Host", "www.rewriteresponseobj.org").bodyValue("hello").exchange()
.expectStatus().isOk().expectHeader().valueEquals("X-TestHeader", "rewrite_response_obj")
.expectBody(String.class)
.consumeWith(result -> assertThat(result.getResponseBody()).isEqualTo("hello"));
webClient.post()
.uri("/post")
.header("Host", "www.rewriteresponseobj.org")
.bodyValue("hello")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-TestHeader", "rewrite_response_obj")
.expectBody(String.class)
.consumeWith(result -> assertThat(result.getResponseBody()).isEqualTo("hello"));
}
@Test
public void complexPredicate() {
webClient.get().uri("/anything/png").header("Host", "www.abc.org").exchange().expectHeader()
.valueEquals("X-TestHeader", "foobar").expectStatus().isOk();
webClient.get()
.uri("/anything/png")
.header("Host", "www.abc.org")
.exchange()
.expectHeader()
.valueEquals("X-TestHeader", "foobar")
.expectStatus()
.isOk();
}
@Test
public void routeFromKotlin() {
webClient.get().uri("/anything/kotlinroute").header("Host", "kotlin.abc.org").exchange().expectHeader()
.valueEquals("X-TestHeader", "foobar").expectStatus().isOk();
webClient.get()
.uri("/anything/kotlinroute")
.header("Host", "kotlin.abc.org")
.exchange()
.expectHeader()
.valueEquals("X-TestHeader", "foobar")
.expectStatus()
.isOk();
}
@Test
public void actuatorManagementPort() {
webClient.get().uri("http://localhost:" + managementPort + "/actuator/gateway/routes").exchange().expectStatus()
.isOk();
webClient.get()
.uri("http://localhost:" + managementPort + "/actuator/gateway/routes")
.exchange()
.expectStatus()
.isOk();
}
@Test
public void actuatorMetrics() {
contextLoads();
String metricName = metricsProperties.getPrefix() + ".requests";
webClient.get().uri("http://localhost:" + managementPort + "/actuator/metrics/" + metricName).exchange()
.expectStatus().isOk().expectBody().consumeWith(i -> {
String body = new String(i.getResponseBodyContent());
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode actualObj = mapper.readTree(body);
JsonNode findValue = actualObj.findValue("name");
assertThat(findValue.asText()).as("Expected to find metric with name gateway.requests")
.isEqualTo(metricName);
}
catch (IOException e) {
throw new IllegalStateException(e);
}
});
webClient.get()
.uri("http://localhost:" + managementPort + "/actuator/metrics/" + metricName)
.exchange()
.expectStatus()
.isOk()
.expectBody()
.consumeWith(i -> {
String body = new String(i.getResponseBodyContent());
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode actualObj = mapper.readTree(body);
JsonNode findValue = actualObj.findValue("name");
assertThat(findValue.asText()).as("Expected to find metric with name gateway.requests")
.isEqualTo(metricName);
}
catch (IOException e) {
throw new IllegalStateException(e);
}
});
}
@Configuration(proxyBeanMethods = false)

View File

@@ -62,16 +62,21 @@ public class GatewaySampleApplicationWithoutMetricsTests {
protected ConfigurableApplicationContext init(Class<?> config) {
return new SpringApplicationBuilder().web(WebApplicationType.REACTIVE)
.sources(GatewaySampleApplication.class, config).run();
.sources(GatewaySampleApplication.class, config)
.run();
}
@Test
public void actuatorMetrics() {
init(TestConfig.class);
webClient.get().uri("/get").exchange().expectStatus().isOk();
webClient.get().uri("http://localhost:" + port + "/actuator/metrics/spring.cloud.gateway.requests").exchange()
.expectStatus().isOk().expectBody(String.class)
.isEqualTo(GatewaySampleApplication.HELLO_FROM_FAKE_ACTUATOR_METRICS_GATEWAY_REQUESTS);
webClient.get()
.uri("http://localhost:" + port + "/actuator/metrics/spring.cloud.gateway.requests")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo(GatewaySampleApplication.HELLO_FROM_FAKE_ACTUATOR_METRICS_GATEWAY_REQUESTS);
}
}

View File

@@ -52,7 +52,7 @@ public class ArgumentSupplierBeanPostProcessor implements BeanPostProcessor {
routerFunction.accept(routerFunctionVisitor);
if (predicateVisitor.argumentSupplier != null) {
ArgumentSuppliedEvent<?> argumentSuppliedEvent = predicateVisitor.argumentSupplier
.getArgumentSuppliedEvent();
.getArgumentSuppliedEvent();
if (predicateVisitor.attributes != null) {
argumentSuppliedEvent = new AttributedArugmentSuppliedEvent<>(argumentSuppliedEvent,
predicateVisitor.attributes);

View File

@@ -144,7 +144,7 @@ public abstract class MvcUtils {
public static ApplicationContext getApplicationContext(ServerRequest request) {
WebApplicationContext webApplicationContext = RequestContextUtils
.findWebApplicationContext(request.servletRequest());
.findWebApplicationContext(request.servletRequest());
if (webApplicationContext == null) {
throw new IllegalStateException("No Application Context in request attributes");
}
@@ -165,16 +165,16 @@ public abstract class MvcUtils {
// attribute resetting in RequestPredicates
// computeIfAbsent if the used vanilla RouterFunctions.route()
Map<String, Object> attributes = (Map<String, Object>) request.attributes()
.computeIfAbsent(GATEWAY_ATTRIBUTES_ATTR, s -> new HashMap<String, Object>());
.computeIfAbsent(GATEWAY_ATTRIBUTES_ATTR, s -> new HashMap<String, Object>());
return attributes;
}
@SuppressWarnings("unchecked")
public static Map<String, Object> getUriTemplateVariables(ServerRequest request) {
Map<String, Object> reqUriTemplateVars = (Map<String, Object>) request.attributes()
.get(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
.get(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
Map<String, Object> gatewayUriTemplateVars = (Map<String, Object>) getGatewayAttributes(request)
.get(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
.get(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
Map<String, Object> merged = mergeMaps(reqUriTemplateVars, gatewayUriTemplateVars);
return merged;
}

View File

@@ -80,8 +80,10 @@ public class WeightConfig {
@Override
public String toString() {
return new ToStringCreator(this).append("routeId", routeId).append("group", group).append("weight", weight)
.toString();
return new ToStringCreator(this).append("routeId", routeId)
.append("group", group)
.append("weight", weight)
.toString();
}
}

View File

@@ -76,7 +76,7 @@ public class GatewayMvcAotRuntimeHintsRegistrar implements RuntimeHintsRegistrar
return; // safety net
}
Arrays.stream(clazz.getMethods())
.forEach(method -> reflectionHints.registerMethod(method, ExecutableMode.INVOKE));
.forEach(method -> reflectionHints.registerMethod(method, ExecutableMode.INVOKE));
}
}

View File

@@ -73,8 +73,10 @@ public class GatewayMvcProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("httpClient", httpClient).append("routes", routes)
.append("routesMap", routesMap).toString();
return new ToStringCreator(this).append("httpClient", httpClient)
.append("routes", routes)
.append("routesMap", routesMap)
.toString();
}
public static class HttpClient {
@@ -125,8 +127,11 @@ public class GatewayMvcProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("connectTimeout", connectTimeout).append("readTimeout", readTimeout)
.append("sslBundle", sslBundle).append("type", type).toString();
return new ToStringCreator(this).append("connectTimeout", connectTimeout)
.append("readTimeout", readTimeout)
.append("sslBundle", sslBundle)
.append("type", type)
.toString();
}
}

View File

@@ -53,9 +53,9 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrar implements ImportBeanDe
// Registers RouterFunctionHolderFactory::routerFunctionHolderSupplier so when the
// bean is refreshed, that method is called again.
AbstractBeanDefinition routerFnProviderBeanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(RouterFunctionHolder.class)
.setFactoryMethodOnBean("routerFunctionHolderSupplier", "routerFunctionHolderFactory")
.getBeanDefinition();
.rootBeanDefinition(RouterFunctionHolder.class)
.setFactoryMethodOnBean("routerFunctionHolderSupplier", "routerFunctionHolderFactory")
.getBeanDefinition();
BeanDefinitionHolder holder = new BeanDefinitionHolder(routerFnProviderBeanDefinition,
"gatewayRouterFunctionHolder");
BeanDefinitionHolder proxy = ScopedProxyUtils.createScopedProxy(holder, registry, true);
@@ -73,7 +73,8 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrar implements ImportBeanDe
// holder can be refreshed and all config based routes will be reloaded.
AbstractBeanDefinition routerFunctionBeanDefinition = BeanDefinitionBuilder
.genericBeanDefinition(DelegatingRouterFunction.class).getBeanDefinition();
.genericBeanDefinition(DelegatingRouterFunction.class)
.getBeanDefinition();
registry.registerBeanDefinition("gatewayCompositeRouterFunction", routerFunctionBeanDefinition);
}

View File

@@ -109,8 +109,8 @@ public class RouterFunctionHolderFactory {
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private GatewayMvcPropertiesBeanDefinitionRegistrar.RouterFunctionHolder routerFunctionHolderSupplier() {
GatewayMvcProperties properties = Binder.get(env).bindOrCreate(GatewayMvcProperties.PREFIX,
GatewayMvcProperties.class);
GatewayMvcProperties properties = Binder.get(env)
.bindOrCreate(GatewayMvcProperties.PREFIX, GatewayMvcProperties.class);
log.trace(LogMessage.format("RouterFunctionHolder initializing with %d map routes and %d list routes",
properties.getRoutesMap().size(), properties.getRoutes().size()));
@@ -242,9 +242,11 @@ public class RouterFunctionHolderFactory {
private Optional<NormalizedOperationMethod> findOperation(MultiValueMap<String, OperationMethod> operations,
String operationName, Map<String, Object> operationArgs) {
return operations.getOrDefault(operationName, Collections.emptyList()).stream()
.map(operationMethod -> new NormalizedOperationMethod(operationMethod, operationArgs))
.filter(opeMethod -> matchOperation(opeMethod, operationArgs)).findFirst();
return operations.getOrDefault(operationName, Collections.emptyList())
.stream()
.map(operationMethod -> new NormalizedOperationMethod(operationMethod, operationArgs))
.filter(opeMethod -> matchOperation(opeMethod, operationArgs))
.findFirst();
}
private static boolean matchOperation(NormalizedOperationMethod operationMethod, Map<String, Object> args) {
@@ -291,7 +293,7 @@ public class RouterFunctionHolderFactory {
}
Bindable<?> bindable = Bindable.of(configurableType);
List<ConfigurationPropertySource> propertySources = Collections
.singletonList(new MapConfigurationPropertySource(args));
.singletonList(new MapConfigurationPropertySource(args));
// TODO: potentially deal with conversion service
Binder binder = new Binder(propertySources, null, DefaultConversionService.getSharedInstance());
Object config = binder.bindOrCreate("", bindable, new IgnoreTopLevelConverterNotFoundBindHandler());

View File

@@ -116,7 +116,8 @@ public abstract class AfterFilterFunctions {
return (request, response) -> {
response.headers().computeIfPresent(name, (key, values) -> {
List<String> rewrittenValues = values.stream()
.map(value -> pattern.matcher(value).replaceAll(replacement)).toList();
.map(value -> pattern.matcher(value).replaceAll(replacement))
.toList();
return new ArrayList<>(rewrittenValues);
});
return response;

View File

@@ -105,8 +105,11 @@ public abstract class BeforeFilterFunctions {
return request -> {
ServerRequest.Builder requestBuilder = ServerRequest.from(request);
newHeaders.forEach((newHeaderName, newHeaderValues) -> {
boolean headerIsMissingOrBlank = request.headers().asHttpHeaders().getOrEmpty(newHeaderName).stream()
.allMatch(h -> !StringUtils.hasText(h));
boolean headerIsMissingOrBlank = request.headers()
.asHttpHeaders()
.getOrEmpty(newHeaderName)
.stream()
.allMatch(h -> !StringUtils.hasText(h));
if (headerIsMissingOrBlank) {
requestBuilder.headers(httpHeaders -> {
List<String> expandedValues = MvcUtils.expandMultiple(request, newHeaderValues);
@@ -134,20 +137,22 @@ public abstract class BeforeFilterFunctions {
Consumer<FallbackHeadersConfig> configConsumer) {
FallbackHeadersConfig config = new FallbackHeadersConfig();
configConsumer.accept(config);
return request -> request.attribute(CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR).map(Throwable.class::cast)
.map(throwable -> ServerRequest.from(request).headers(httpHeaders -> {
httpHeaders.add(config.getExecutionExceptionTypeHeaderName(), throwable.getClass().getName());
if (throwable.getMessage() != null) {
httpHeaders.add(config.getExecutionExceptionMessageHeaderName(), throwable.getMessage());
return request -> request.attribute(CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR)
.map(Throwable.class::cast)
.map(throwable -> ServerRequest.from(request).headers(httpHeaders -> {
httpHeaders.add(config.getExecutionExceptionTypeHeaderName(), throwable.getClass().getName());
if (throwable.getMessage() != null) {
httpHeaders.add(config.getExecutionExceptionMessageHeaderName(), throwable.getMessage());
}
Throwable rootCause = getRootCause(throwable);
if (rootCause != null) {
httpHeaders.add(config.getRootCauseExceptionTypeHeaderName(), rootCause.getClass().getName());
if (rootCause.getMessage() != null) {
httpHeaders.add(config.getRootCauseExceptionMessageHeaderName(), rootCause.getMessage());
}
Throwable rootCause = getRootCause(throwable);
if (rootCause != null) {
httpHeaders.add(config.getRootCauseExceptionTypeHeaderName(), rootCause.getClass().getName());
if (rootCause.getMessage() != null) {
httpHeaders.add(config.getRootCauseExceptionMessageHeaderName(), rootCause.getMessage());
}
}
}).build()).orElse(request);
}
}).build())
.orElse(request);
}
private static Throwable getRootCause(Throwable throwable) {
@@ -211,7 +216,9 @@ public abstract class BeforeFilterFunctions {
// remove from uri
URI newUri = UriComponentsBuilder.fromUri(request.uri())
.replaceQueryParams(unmodifiableMultiValueMap(queryParams)).build().toUri();
.replaceQueryParams(unmodifiableMultiValueMap(queryParams))
.build()
.toUri();
// remove resolved params from request
return ServerRequest.from(request).params(params -> params.remove(name)).uri(newUri).build();
@@ -252,7 +259,7 @@ public abstract class BeforeFilterFunctions {
StringBuilder errorMessage = new StringBuilder(
String.format(REQUEST_HEADER_SIZE_ERROR_PREFIX, maxSize));
longHeaders.forEach((header, size) -> errorMessage
.append(String.format(REQUEST_HEADER_SIZE_ERROR, header, DataSize.of(size, DataUnit.BYTES))));
.append(String.format(REQUEST_HEADER_SIZE_ERROR, header, DataSize.of(size, DataUnit.BYTES))));
throw new ResponseStatusException(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE, errorMessage.toString()) {
@Override
@@ -398,8 +405,10 @@ public abstract class BeforeFilterFunctions {
}
// TODO: end duplicate code from StripPrefixGatewayFilterFactory
URI prefixedUri = UriComponentsBuilder.fromUri(request.uri()).replacePath(newPath.toString()).build()
.toUri();
URI prefixedUri = UriComponentsBuilder.fromUri(request.uri())
.replacePath(newPath.toString())
.build()
.toUri();
return ServerRequest.from(request).uri(prefixedUri).build();
};
}

View File

@@ -128,7 +128,8 @@ public abstract class BodyFilterFunctions {
ByteArrayHttpOutputMessage outputMessage = new ByteArrayHttpOutputMessage(headers);
((HttpMessageConverter<R>) messageConverter).write(convertedBody, contentType, outputMessage);
ServerRequest modified = ServerRequest.from(request)
.headers(httpHeaders -> httpHeaders.putAll(headers)).build();
.headers(httpHeaders -> httpHeaders.putAll(headers))
.build();
return wrapRequest(modified, outputMessage.getBytes());
}
catch (IOException e) {

View File

@@ -45,9 +45,12 @@ public abstract class Bucket4jFilterFunctions {
public static final String DEFAULT_HEADER_NAME = "X-RateLimit-Remaining";
private static final Function<RateLimitConfig, BucketConfiguration> DEFAULT_CONFIGURATION_BUILDER = config -> BucketConfiguration
.builder().addLimit(Bandwidth.builder().capacity(config.getCapacity())
.refillGreedy(config.getCapacity(), config.getPeriod()).build())
.build();
.builder()
.addLimit(Bandwidth.builder()
.capacity(config.getCapacity())
.refillGreedy(config.getCapacity(), config.getPeriod())
.build())
.build();
private Bucket4jFilterFunctions() {
}
@@ -87,7 +90,8 @@ public abstract class Bucket4jFilterFunctions {
return serverResponse;
}
return ServerResponse.status(config.getStatusCode())
.header(config.getHeaderName(), String.valueOf(remainingTokens)).build();
.header(config.getHeaderName(), String.valueOf(remainingTokens))
.build();
};
}

View File

@@ -71,11 +71,13 @@ public abstract class CircuitBreakerFilterFunctions {
@Shortcut
@Configurable
public static HandlerFilterFunction<ServerResponse, ServerResponse> circuitBreaker(CircuitBreakerConfig config) {
Set<HttpStatusCode> failureStatuses = config.getStatusCodes().stream()
.map(status -> HttpStatusHolder.valueOf(status).resolve()).collect(Collectors.toSet());
Set<HttpStatusCode> failureStatuses = config.getStatusCodes()
.stream()
.map(status -> HttpStatusHolder.valueOf(status).resolve())
.collect(Collectors.toSet());
return (request, next) -> {
CircuitBreakerFactory<?, ?> circuitBreakerFactory = MvcUtils.getApplicationContext(request)
.getBean(CircuitBreakerFactory.class);
.getBean(CircuitBreakerFactory.class);
// TODO: cache
CircuitBreaker circuitBreaker = circuitBreakerFactory.create(config.getId());
return circuitBreaker.run(() -> {
@@ -117,8 +119,10 @@ public abstract class CircuitBreakerFilterFunctions {
return GatewayServerResponse.ok().build((httpServletRequest, httpServletResponse) -> {
try {
String expandedFallback = MvcUtils.expand(request, config.getFallbackPath());
request.servletRequest().getServletContext().getRequestDispatcher(expandedFallback)
.forward(httpServletRequest, httpServletResponse);
request.servletRequest()
.getServletContext()
.getRequestDispatcher(expandedFallback)
.forward(httpServletRequest, httpServletResponse);
return null;
}
catch (ServletException | IOException e) {

View File

@@ -117,8 +117,8 @@ public interface FilterFunctions {
static HandlerFilterFunction<ServerResponse, ServerResponse> redirectTo(HttpStatusHolder status, URI uri) {
Assert.isTrue(status.is3xxRedirection(), "status must be a 3xx code, but was " + status);
return (request, next) -> ServerResponse.status(status.resolve()).header(HttpHeaders.LOCATION, uri.toString())
.build();
return (request,
next) -> ServerResponse.status(status.resolve()).header(HttpHeaders.LOCATION, uri.toString()).build();
}
@Shortcut
@@ -162,9 +162,11 @@ public interface FilterFunctions {
@Shortcut
static HandlerFilterFunction<ServerResponse, ServerResponse> rewriteLocationResponseHeader(String stripVersion,
String locationHeaderName, String hostValue, String protocolsRegex) {
return ofResponseProcessor(RewriteLocationResponseHeaderFilterFunctions.rewriteLocationResponseHeader(
config -> config.setStripVersion(stripVersion).setLocationHeaderName(locationHeaderName)
.setHostValue(hostValue).setProtocolsRegex(protocolsRegex)));
return ofResponseProcessor(RewriteLocationResponseHeaderFilterFunctions
.rewriteLocationResponseHeader(config -> config.setStripVersion(stripVersion)
.setLocationHeaderName(locationHeaderName)
.setHostValue(hostValue)
.setProtocolsRegex(protocolsRegex)));
}
@Shortcut

View File

@@ -121,7 +121,7 @@ public class FormFilter implements Filter, Ordered {
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(requestURL.toString());
MultiValueMap<String, String> queryParams = uriComponentsBuilder.build().getQueryParams();
for (Iterator<Map.Entry<String, String[]>> entryIterator = form.entrySet().iterator(); entryIterator
.hasNext();) {
.hasNext();) {
Map.Entry<String, String[]> entry = entryIterator.next();
String name = entry.getKey();
List<String> values = Arrays.asList(entry.getValue());

View File

@@ -64,10 +64,10 @@ public abstract class LoadBalancerFilterFunctions {
BiFunction<ServiceInstance, URI, URI> reconstructUriFunction) {
return (request, next) -> {
LoadBalancerClientFactory clientFactory = getApplicationContext(request)
.getBean(LoadBalancerClientFactory.class);
.getBean(LoadBalancerClientFactory.class);
Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
.getSupportedLifecycleProcessors(clientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
.getSupportedLifecycleProcessors(clientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
RequestData requestData = new RequestData(request.method(), request.uri(),
request.headers().asHttpHeaders(), buildCookies(request.cookies()), request.attributes());
DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(
@@ -82,7 +82,7 @@ public abstract class LoadBalancerFilterFunctions {
ServiceInstance retrievedInstance = loadBalancerClient.choose(serviceId, lbRequest);
if (retrievedInstance == null) {
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest)));
.onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest)));
throw new HttpServerErrorException(HttpStatus.SERVICE_UNAVAILABLE,
"Unable to find instance for " + serviceId);
// throw NotFoundException.create(properties.isUse404(), "Unable to find
@@ -110,9 +110,9 @@ public abstract class LoadBalancerFilterFunctions {
try {
ServerResponse serverResponse = next.handle(request);
supportedLifecycleProcessors.forEach(
lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
lbRequest, defaultResponse, serverResponse)));
supportedLifecycleProcessors
.forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
lbRequest, defaultResponse, serverResponse)));
return serverResponse;
}
catch (Exception e) {
@@ -136,7 +136,7 @@ public abstract class LoadBalancerFilterFunctions {
HttpHeaders newCookies = new HttpHeaders();
if (cookies != null) {
cookies.forEach((key, value) -> value
.forEach(cookie -> newCookies.put(cookie.getName(), Collections.singletonList(cookie.getValue()))));
.forEach(cookie -> newCookies.put(cookie.getName(), Collections.singletonList(cookie.getValue()))));
}
return newCookies;
}

View File

@@ -67,7 +67,7 @@ public abstract class RetryFilterFunctions {
config.getExceptions().forEach(exception -> retryableExceptions.put(exception, true));
SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy(config.getRetries(), retryableExceptions);
compositeRetryPolicy
.setPolicies(Arrays.asList(simpleRetryPolicy, new HttpRetryPolicy(config)).toArray(new RetryPolicy[0]));
.setPolicies(Arrays.asList(simpleRetryPolicy, new HttpRetryPolicy(config)).toArray(new RetryPolicy[0]));
RetryTemplate retryTemplate = retryTemplateBuilder.customPolicy(compositeRetryPolicy).build();
return (request, next) -> retryTemplate.execute(context -> {
ServerResponse serverResponse = next.handle(request);

View File

@@ -42,13 +42,16 @@ public abstract class TokenRelayFilterFunctions {
if (principle instanceof OAuth2AuthenticationToken token) {
String clientRegistrationId = token.getAuthorizedClientRegistrationId();
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
.withClientRegistrationId(clientRegistrationId).principal(token).build();
.withClientRegistrationId(clientRegistrationId)
.principal(token)
.build();
OAuth2AuthorizedClientManager clientManager = getApplicationContext(request)
.getBean(OAuth2AuthorizedClientManager.class);
.getBean(OAuth2AuthorizedClientManager.class);
OAuth2AuthorizedClient authorizedClient = clientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
ServerRequest modified = ServerRequest.from(request)
.headers(httpHeaders -> httpHeaders.setBearerAuth(accessToken.getTokenValue())).build();
.headers(httpHeaders -> httpHeaders.setBearerAuth(accessToken.getTokenValue()))
.build();
return next.handle(modified);
}
return next.handle(request);

View File

@@ -254,8 +254,11 @@ public class WeightCalculatorFilter implements Filter, Ordered, SmartApplication
@Override
public String toString() {
return new ToStringCreator(this).append("group", group).append("weights", weights)
.append("normalizedWeights", normalizedWeights).append("rangeIndexes", rangeIndexes).toString();
return new ToStringCreator(this).append("group", group)
.append("weights", weights)
.append("normalizedWeights", normalizedWeights)
.append("rangeIndexes", rangeIndexes)
.toString();
}
}

View File

@@ -47,20 +47,20 @@ public class ClientHttpRequestFactoryProxyExchange implements ProxyExchange {
// put the body input stream in a request attribute so filters can read it.
MvcUtils.putAttribute(request.getServerRequest(), MvcUtils.CLIENT_RESPONSE_INPUT_STREAM_ATTR, body);
ServerResponse serverResponse = GatewayServerResponse.status(clientHttpResponse.getStatusCode())
.build((req, httpServletResponse) -> {
try (clientHttpResponse) {
// get input stream from request attribute in case it was
// modified.
InputStream inputStream = MvcUtils.getAttribute(request.getServerRequest(),
MvcUtils.CLIENT_RESPONSE_INPUT_STREAM_ATTR);
// copy body from request to clientHttpRequest
StreamUtils.copy(inputStream, httpServletResponse.getOutputStream());
}
return null;
});
.build((req, httpServletResponse) -> {
try (clientHttpResponse) {
// get input stream from request attribute in case it was
// modified.
InputStream inputStream = MvcUtils.getAttribute(request.getServerRequest(),
MvcUtils.CLIENT_RESPONSE_INPUT_STREAM_ATTR);
// copy body from request to clientHttpRequest
StreamUtils.copy(inputStream, httpServletResponse.getOutputStream());
}
return null;
});
ClientHttpResponseAdapter proxyExchangeResponse = new ClientHttpResponseAdapter(clientHttpResponse);
request.getResponseConsumers()
.forEach(responseConsumer -> responseConsumer.accept(proxyExchangeResponse, serverResponse));
.forEach(responseConsumer -> responseConsumer.accept(proxyExchangeResponse, serverResponse));
return serverResponse;
}
catch (IOException e) {

View File

@@ -268,10 +268,10 @@ final class GatewayEntityResponseBuilder<T> implements EntityResponse.Builder<T>
entityType = RESOURCE_REGION_LIST_TYPE;
}
catch (IllegalArgumentException ex) {
serverResponse.getHeaders().set(HttpHeaders.CONTENT_RANGE,
"bytes */" + resource.contentLength());
serverResponse.getHeaders()
.set(HttpHeaders.CONTENT_RANGE, "bytes */" + resource.contentLength());
serverResponse.getServletResponse()
.setStatus(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value());
.setStatus(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value());
}
}
}
@@ -316,9 +316,10 @@ final class GatewayEntityResponseBuilder<T> implements EntityResponse.Builder<T>
private static List<MediaType> producibleMediaTypes(List<HttpMessageConverter<?>> messageConverters,
Class<?> entityClass) {
return messageConverters.stream().filter(messageConverter -> messageConverter.canWrite(entityClass, null))
.flatMap(messageConverter -> messageConverter.getSupportedMediaTypes(entityClass).stream())
.toList();
return messageConverters.stream()
.filter(messageConverter -> messageConverter.canWrite(entityClass, null))
.flatMap(messageConverter -> messageConverter.getSupportedMediaTypes(entityClass).stream())
.toList();
}
}

View File

@@ -79,7 +79,7 @@ abstract class GatewayErrorHandlingServerResponse implements ServerResponse {
for (ErrorHandler<?> errorHandler : this.errorHandlers) {
if (errorHandler.test(t)) {
ServerRequest serverRequest = (ServerRequest) servletRequest
.getAttribute(RouterFunctions.REQUEST_ATTRIBUTE);
.getAttribute(RouterFunctions.REQUEST_ATTRIBUTE);
return errorHandler.handle(t, serverRequest);
}
}

View File

@@ -49,7 +49,7 @@ public interface GatewayServerResponse extends ServerResponse {
*/
static ServerResponse from(ErrorResponse response) {
return status(response.getStatusCode()).headers(headers -> headers.putAll(response.getHeaders()))
.body(response.getBody());
.body(response.getBody());
}
/**

View File

@@ -173,30 +173,38 @@ class GatewayServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override
public ServerResponse body(Object body) {
return GatewayEntityResponseBuilder.fromObject(body).status(this.statusCode)
.headers(headers -> headers.putAll(this.headers)).cookies(cookies -> cookies.addAll(this.cookies))
.build();
return GatewayEntityResponseBuilder.fromObject(body)
.status(this.statusCode)
.headers(headers -> headers.putAll(this.headers))
.cookies(cookies -> cookies.addAll(this.cookies))
.build();
}
@Override
public <T> ServerResponse body(T body, ParameterizedTypeReference<T> bodyType) {
return GatewayEntityResponseBuilder.fromObject(body, bodyType).status(this.statusCode)
.headers(headers -> headers.putAll(this.headers)).cookies(cookies -> cookies.addAll(this.cookies))
.build();
return GatewayEntityResponseBuilder.fromObject(body, bodyType)
.status(this.statusCode)
.headers(headers -> headers.putAll(this.headers))
.cookies(cookies -> cookies.addAll(this.cookies))
.build();
}
@Override
public ServerResponse render(String name, Object... modelAttributes) {
return new GatewayRenderingResponseBuilder(name).status(this.statusCode)
.headers(headers -> headers.putAll(this.headers)).cookies(cookies -> cookies.addAll(this.cookies))
.modelAttributes(modelAttributes).build();
.headers(headers -> headers.putAll(this.headers))
.cookies(cookies -> cookies.addAll(this.cookies))
.modelAttributes(modelAttributes)
.build();
}
@Override
public ServerResponse render(String name, Map<String, ?> model) {
return new GatewayRenderingResponseBuilder(name).status(this.statusCode)
.headers(headers -> headers.putAll(this.headers)).cookies(cookies -> cookies.addAll(this.cookies))
.modelAttributes(model).build();
.headers(headers -> headers.putAll(this.headers))
.cookies(cookies -> cookies.addAll(this.cookies))
.modelAttributes(model)
.build();
}
private static class WriteFunctionResponse extends AbstractGatewayServerResponse {

View File

@@ -46,8 +46,10 @@ public abstract class HandlerFunctions {
return request -> GatewayServerResponse.ok().build((httpServletRequest, httpServletResponse) -> {
try {
String expandedFallback = MvcUtils.expand(request, path);
request.servletRequest().getServletContext().getRequestDispatcher(expandedFallback)
.forward(httpServletRequest, httpServletResponse);
request.servletRequest()
.getServletContext()
.getRequestDispatcher(expandedFallback)
.forward(httpServletRequest, httpServletResponse);
return null;
}
catch (ServletException | IOException e) {

View File

@@ -59,7 +59,7 @@ public class ProxyExchangeHandlerFunction
ObjectProvider<ResponseHttpHeadersFilter> responseHttpHeadersFilters) {
this(proxyExchange, requestHttpHeadersFilters, responseHttpHeadersFilters,
request -> (URI) request.attribute(MvcUtils.GATEWAY_REQUEST_URL_ATTR)
.orElseThrow(() -> new IllegalStateException("No routeUri resolved")));
.orElseThrow(() -> new IllegalStateException("No routeUri resolved")));
}
public ProxyExchangeHandlerFunction(ProxyExchange proxyExchange,
@@ -99,7 +99,7 @@ public class ProxyExchangeHandlerFunction
serverRequest.headers().asHttpHeaders(), serverRequest);
boolean preserveHost = (boolean) serverRequest.attributes()
.getOrDefault(MvcUtils.PRESERVE_HOST_HEADER_ATTRIBUTE, false);
.getOrDefault(MvcUtils.PRESERVE_HOST_HEADER_ATTRIBUTE, false);
if (preserveHost) {
filteredRequestHeaders.set(HttpHeaders.HOST, serverRequest.headers().firstHeader(HttpHeaders.HOST));
}

View File

@@ -36,10 +36,11 @@ public class RestClientProxyExchange implements ProxyExchange {
@Override
public ServerResponse exchange(Request request) {
return restClient.method(request.getMethod()).uri(request.getUri())
.headers(httpHeaders -> httpHeaders.putAll(request.getHeaders()))
.body(outputStream -> copyBody(request, outputStream))
.exchange((clientRequest, clientResponse) -> doExchange(request, clientResponse), false);
return restClient.method(request.getMethod())
.uri(request.getUri())
.headers(httpHeaders -> httpHeaders.putAll(request.getHeaders()))
.body(outputStream -> copyBody(request, outputStream))
.exchange((clientRequest, clientResponse) -> doExchange(request, clientResponse), false);
}
private static int copyBody(Request request, OutputStream outputStream) throws IOException {
@@ -51,20 +52,20 @@ public class RestClientProxyExchange implements ProxyExchange {
// put the body input stream in a request attribute so filters can read it.
MvcUtils.putAttribute(request.getServerRequest(), MvcUtils.CLIENT_RESPONSE_INPUT_STREAM_ATTR, body);
ServerResponse serverResponse = GatewayServerResponse.status(clientResponse.getStatusCode())
.build((req, httpServletResponse) -> {
try (clientResponse) {
// get input stream from request attribute in case it was
// modified.
InputStream inputStream = MvcUtils.getAttribute(request.getServerRequest(),
MvcUtils.CLIENT_RESPONSE_INPUT_STREAM_ATTR);
// copy body from request to clientHttpRequest
StreamUtils.copy(inputStream, httpServletResponse.getOutputStream());
}
return null;
});
.build((req, httpServletResponse) -> {
try (clientResponse) {
// get input stream from request attribute in case it was
// modified.
InputStream inputStream = MvcUtils.getAttribute(request.getServerRequest(),
MvcUtils.CLIENT_RESPONSE_INPUT_STREAM_ATTR);
// copy body from request to clientHttpRequest
StreamUtils.copy(inputStream, httpServletResponse.getOutputStream());
}
return null;
});
ClientHttpResponseAdapter proxyExchangeResponse = new ClientHttpResponseAdapter(clientResponse);
request.getResponseConsumers()
.forEach(responseConsumer -> responseConsumer.accept(proxyExchangeResponse, serverResponse));
.forEach(responseConsumer -> responseConsumer.accept(proxyExchangeResponse, serverResponse));
return serverResponse;
}

View File

@@ -84,10 +84,10 @@ class OperationMethodParameter implements OperationParameter {
boolean isMandatory(Parameter parameter) {
MergedAnnotation<Nonnull> annotation = MergedAnnotations.from(parameter).get(Nonnull.class);
return !annotation.isPresent()/*
* || annotation.getEnum("when", When.class)
* == When.ALWAYS
*/;
return !annotation
.isPresent()/*
* || annotation.getEnum("when", When.class) == When.ALWAYS
*/;
}
}

View File

@@ -88,8 +88,10 @@ public class ReflectiveOperationInvoker implements OperationInvoker {
}
private void validateRequiredParameters(InvocationContext context) {
Set<OperationParameter> missing = this.operationMethod.getParameters().stream()
.filter((parameter) -> isMissing(context, parameter)).collect(Collectors.toSet());
Set<OperationParameter> missing = this.operationMethod.getParameters()
.stream()
.filter((parameter) -> isMissing(context, parameter))
.collect(Collectors.toSet());
if (!missing.isEmpty()) {
throw new MissingParametersException(missing);
}
@@ -106,8 +108,10 @@ public class ReflectiveOperationInvoker implements OperationInvoker {
}
private Object[] resolveArguments(InvocationContext context) {
return this.operationMethod.getParameters().stream().map((parameter) -> resolveArgument(parameter, context))
.toArray();
return this.operationMethod.getParameters()
.stream()
.map((parameter) -> resolveArgument(parameter, context))
.toArray();
}
private Object resolveArgument(OperationParameter parameter, InvocationContext context) {
@@ -121,8 +125,9 @@ public class ReflectiveOperationInvoker implements OperationInvoker {
@Override
public String toString() {
return new ToStringCreator(this).append("target", this.target).append("method", this.operationMethod)
.toString();
return new ToStringCreator(this).append("target", this.target)
.append("method", this.operationMethod)
.toString();
}
}

View File

@@ -533,8 +533,8 @@ public abstract class GatewayRequestPredicates {
@SuppressWarnings("unchecked")
@Override
public boolean test(ServerRequest request) {
Map<String, String> weights = (Map<String, String>) request.attributes().getOrDefault(WEIGHT_ATTR,
Collections.emptyMap());
Map<String, String> weights = (Map<String, String>) request.attributes()
.getOrDefault(WEIGHT_ATTR, Collections.emptyMap());
String routeId = (String) request.attributes().get(GATEWAY_ROUTE_ID_ATTR);
if (ObjectUtils.isEmpty(routeId)) {

View File

@@ -38,26 +38,27 @@ public class GatewayServerMvcAutoConfigurationTests {
@Test
void filterEnabledPropertiesWork() {
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(GatewayServerMvcAutoConfiguration.class,
RestTemplateAutoConfiguration.class, RestClientAutoConfiguration.class, SslAutoConfiguration.class))
.withPropertyValues("spring.cloud.gateway.mvc.form-filter.enabled=false",
"spring.cloud.gateway.mvc.forwarded-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-content-length-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-hop-by-hop-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-hop-by-hop-response-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.weight-calculator-filter.enabled=false",
"spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.enabled=false")
.run(context -> {
assertThat(context).doesNotHaveBean(FormFilter.class);
assertThat(context).doesNotHaveBean(ForwardedRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(RemoveContentLengthRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(RemoveHopByHopRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(RemoveHopByHopResponseHeadersFilter.class);
assertThat(context).doesNotHaveBean(TransferEncodingNormalizationRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(WeightCalculatorFilter.class);
assertThat(context).doesNotHaveBean(XForwardedRequestHeadersFilter.class);
});
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(GatewayServerMvcAutoConfiguration.class,
RestTemplateAutoConfiguration.class, RestClientAutoConfiguration.class, SslAutoConfiguration.class))
.withPropertyValues("spring.cloud.gateway.mvc.form-filter.enabled=false",
"spring.cloud.gateway.mvc.forwarded-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-content-length-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-hop-by-hop-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.remove-hop-by-hop-response-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.transfer-encoding-normalization-request-headers-filter.enabled=false",
"spring.cloud.gateway.mvc.weight-calculator-filter.enabled=false",
"spring.cloud.gateway.mvc.x-forwarded-request-headers-filter.enabled=false")
.run(context -> {
assertThat(context).doesNotHaveBean(FormFilter.class);
assertThat(context).doesNotHaveBean(ForwardedRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(RemoveContentLengthRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(RemoveHopByHopRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(RemoveHopByHopResponseHeadersFilter.class);
assertThat(context).doesNotHaveBean(TransferEncodingNormalizationRequestHeadersFilter.class);
assertThat(context).doesNotHaveBean(WeightCalculatorFilter.class);
assertThat(context).doesNotHaveBean(XForwardedRequestHeadersFilter.class);
});
}
}

View File

@@ -178,131 +178,208 @@ public class ServerMvcIntegrationTests {
@Test
public void addRequestParameterWorks() {
restClient.get().uri("/anything/addrequestparam").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> args = getMap(map, "args");
assertThat(args).containsEntry("param1", "param1val");
});
restClient.get()
.uri("/anything/addrequestparam")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> args = getMap(map, "args");
assertThat(args).containsEntry("param1", "param1val");
});
}
@Test
public void removeHopByHopRequestHeadersFilterWorks() {
restClient.get().uri("/anything/removehopbyhoprequestheaders").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).doesNotContainKeys("x-application-context");
});
restClient.get()
.uri("/anything/removehopbyhoprequestheaders")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).doesNotContainKeys("x-application-context");
});
}
@Test
public void setPathWorks() {
restClient.get().uri("/mycustompathextra1").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> args = getMap(map, "args");
assertThat(args).containsEntry("param1", "param1valextra1");
});
restClient.get()
.uri("/mycustompathextra1")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> args = getMap(map, "args");
assertThat(args).containsEntry("param1", "param1valextra1");
});
}
@Test
public void setPathPostWorks() {
restClient.post().uri("/mycustompathpost").bodyValue("hello").header("Host", "www.setpathpost.org").exchange()
.expectStatus().isOk().expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).containsEntry("data", "hello");
});
restClient.post()
.uri("/mycustompathpost")
.bodyValue("hello")
.header("Host", "www.setpathpost.org")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).containsEntry("data", "hello");
});
}
@Test
public void stripPrefixWorks() {
restClient.get().uri("/long/path/to/get").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "stripPrefix");
});
restClient.get()
.uri("/long/path/to/get")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "stripPrefix");
});
}
@Test
public void stripPrefixPostWorks() {
restClient.post().uri("/long/path/to/post").bodyValue("hello").header("Host", "www.stripprefixpost.org")
.exchange().expectStatus().isOk().expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).containsEntry("data", "hello");
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "stripPrefixPost");
});
restClient.post()
.uri("/long/path/to/post")
.bodyValue("hello")
.header("Host", "www.stripprefixpost.org")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).containsEntry("data", "hello");
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "stripPrefixPost");
});
}
@Test
public void setStatusGatewayRouterFunctionWorks() {
restClient.get().uri("/status/201").exchange().expectStatus().isEqualTo(HttpStatus.TOO_MANY_REQUESTS)
.expectHeader().valueEquals("x-status", "201"); // .expectBody(String.class).isEqualTo("Failed
// with 201");
restClient.get()
.uri("/status/201")
.exchange()
.expectStatus()
.isEqualTo(HttpStatus.TOO_MANY_REQUESTS)
.expectHeader()
.valueEquals("x-status", "201"); // .expectBody(String.class).isEqualTo("Failed
// with 201");
}
@Test
public void addResponseHeaderWorks() {
restClient.get().uri("/anything/addresheader").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).doesNotContainKey("x-bar");
assertThat(res.getResponseHeaders()).containsEntry("x-bar", Collections.singletonList("val1"));
});
restClient.get()
.uri("/anything/addresheader")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).doesNotContainKey("x-bar");
assertThat(res.getResponseHeaders()).containsEntry("x-bar", Collections.singletonList("val1"));
});
}
@Test
public void postWorks() {
restClient.post().uri("/post").bodyValue("Post Value").header("test", "post").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).isNotEmpty().containsEntry("data", "Post Value");
});
restClient.post()
.uri("/post")
.bodyValue("Post Value")
.header("test", "post")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).isNotEmpty().containsEntry("data", "Post Value");
});
}
@Test
public void loadbalancerWorks() {
restClient.get().uri("/anything/loadbalancer").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "loadbalancer");
});
restClient.get()
.uri("/anything/loadbalancer")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "loadbalancer");
});
}
@Test
public void hostPredicateWorks() {
String host = "www1.myjavadslhost.com";
restClient.get().uri("/anything/hostpredicate").header("Host", host).exchange().expectStatus().isOk()
.expectHeader().valueEquals("X-SubDomain", "www1").expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("Host", host);
});
restClient.get()
.uri("/anything/hostpredicate")
.header("Host", host)
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-SubDomain", "www1")
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("Host", host);
});
}
@Test
public void circuitBreakerFallbackWorks() {
restClient.get().uri("/anything/circuitbreakerfallback").exchange().expectStatus().isOk()
.expectBody(String.class).isEqualTo("Hello");
restClient.get()
.uri("/anything/circuitbreakerfallback")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("Hello");
}
@Test
public void circuitBreakerGatewayFallbackWorks() {
restClient.get().uri("/anything/circuitbreakergatewayfallback").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsKeys(CB_EXECUTION_EXCEPTION_TYPE, CB_EXECUTION_EXCEPTION_MESSAGE);
});
restClient.get()
.uri("/anything/circuitbreakergatewayfallback")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsKeys(CB_EXECUTION_EXCEPTION_TYPE, CB_EXECUTION_EXCEPTION_MESSAGE);
});
}
@Test
public void circuitBreakerNoFallbackWorks() {
restClient.get().uri("/anything/circuitbreakernofallback").exchange().expectStatus()
.isEqualTo(HttpStatus.GATEWAY_TIMEOUT);
restClient.get()
.uri("/anything/circuitbreakernofallback")
.exchange()
.expectStatus()
.isEqualTo(HttpStatus.GATEWAY_TIMEOUT);
}
@Test
@@ -320,8 +397,13 @@ public class ServerMvcIntegrationTests {
restClient.get().uri("/retry?key=get").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("3");
// test for: java.lang.IllegalArgumentException: You have already selected another
// retry policy
restClient.get().uri("/retry?key=get2").exchange().expectStatus().isOk().expectBody(String.class)
.isEqualTo("3");
restClient.get()
.uri("/retry?key=get2")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("3");
}
@Test
@@ -333,97 +415,152 @@ public class ServerMvcIntegrationTests {
@Test
public void headerRegexWorks() {
restClient.get().uri("/headerregex").exchange().expectStatus().isNotFound();
restClient.get().uri("/headerregex").header("X-MyHeader", "foo").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Myheader", "foo");
});
restClient.get()
.uri("/headerregex")
.header("X-MyHeader", "foo")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Myheader", "foo");
});
}
@Test
public void cookieRegexWorks() {
restClient.get().uri("/cookieregex").exchange().expectStatus().isNotFound();
restClient.get().uri("/cookieregex").cookie("mycookie", "foo").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("Cookie", "mycookie=foo");
});
restClient.get()
.uri("/cookieregex")
.cookie("mycookie", "foo")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("Cookie", "mycookie=foo");
});
}
@Test
public void rewritePathWorks() {
restClient.get().uri("/foo/get").header("Host", "www.rewritepath.org").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "rewritepath");
});
restClient.get()
.uri("/foo/get")
.header("Host", "www.rewritepath.org")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "rewritepath");
});
}
@Test
public void rewritePathPostWorks() {
restClient.post().uri("/baz/post").bodyValue("hello").header("Host", "www.rewritepathpost.org").exchange()
.expectStatus().isOk().expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).containsEntry("data", "hello");
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "rewritepathpost");
});
restClient.post()
.uri("/baz/post")
.bodyValue("hello")
.header("Host", "www.rewritepathpost.org")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).containsEntry("data", "hello");
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("X-Test", "rewritepathpost");
});
}
@Test
public void rewritePathPostLocalWorks() {
restClient.post().uri("/baz/post").bodyValue("hello").header("Host", "www.rewritepathpostlocal.org").exchange()
.expectStatus().isOk().expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).containsEntry("data", "hello");
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("x-test", "rewritepathpostlocal");
});
restClient.post()
.uri("/baz/post")
.bodyValue("hello")
.header("Host", "www.rewritepathpostlocal.org")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
assertThat(map).containsEntry("data", "hello");
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsEntry("x-test", "rewritepathpostlocal");
});
}
@Test
public void forwardedHeadersWork() {
restClient.get().uri("/headers").header("test", "forwarded").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsKeys(ForwardedRequestHeadersFilter.FORWARDED_HEADER,
XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER,
XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER,
XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER,
XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER);
assertThat(headers.get(ForwardedRequestHeadersFilter.FORWARDED_HEADER)).asString()
.contains("proto=http").contains("host=\"localhost:").contains("for=\"127.0.0.1:");
assertThat(headers.get(XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER)).asString()
.isEqualTo("localhost:" + this.port);
assertThat(headers.get(XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER)).asString()
.isEqualTo(String.valueOf(this.port));
assertThat(headers.get(XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER).toString())
.asString().isEqualTo("http");
});
restClient.get()
.uri("/headers")
.header("test", "forwarded")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).containsKeys(ForwardedRequestHeadersFilter.FORWARDED_HEADER,
XForwardedRequestHeadersFilter.X_FORWARDED_FOR_HEADER,
XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER,
XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER,
XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER);
assertThat(headers.get(ForwardedRequestHeadersFilter.FORWARDED_HEADER)).asString()
.contains("proto=http")
.contains("host=\"localhost:")
.contains("for=\"127.0.0.1:");
assertThat(headers.get(XForwardedRequestHeadersFilter.X_FORWARDED_HOST_HEADER)).asString()
.isEqualTo("localhost:" + this.port);
assertThat(headers.get(XForwardedRequestHeadersFilter.X_FORWARDED_PORT_HEADER)).asString()
.isEqualTo(String.valueOf(this.port));
assertThat(headers.get(XForwardedRequestHeadersFilter.X_FORWARDED_PROTO_HEADER).toString()).asString()
.isEqualTo("http");
});
}
@Test
public void requestSizeWorks() {
restClient.post().uri("/post").bodyValue("123456").header("test", "requestsize").exchange().expectStatus()
.isEqualTo(HttpStatus.PAYLOAD_TOO_LARGE).expectHeader().valueMatches("errormessage",
"Request size is larger than permissible limit. Request size is .* where permissible limit is .*");
restClient.post()
.uri("/post")
.bodyValue("123456")
.header("test", "requestsize")
.exchange()
.expectStatus()
.isEqualTo(HttpStatus.PAYLOAD_TOO_LARGE)
.expectHeader()
.valueMatches("errormessage",
"Request size is larger than permissible limit. Request size is .* where permissible limit is .*");
}
@Test
public void requestHeaderSizeWorks() {
restClient.get().uri("/headers").header("test", "requestheadersize")
.header("X-AnyHeader",
"11111111112222222222333333333344444444445555555555666666666677777777778888888888")
.exchange().expectStatus().isEqualTo(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE).expectHeader()
.valueMatches("errormessage",
"Request Header/s size is larger than permissible limit (.*). Request Header/s size for 'x-anyheader' is .*");
restClient.get().uri("/headers").header("test", "requestheadersize")
.header("X-AnyHeader", "111111111122222222223333333333444444444455555555556666666666").exchange()
.expectStatus().isOk();
restClient.get()
.uri("/headers")
.header("test", "requestheadersize")
.header("X-AnyHeader", "11111111112222222222333333333344444444445555555555666666666677777777778888888888")
.exchange()
.expectStatus()
.isEqualTo(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE)
.expectHeader()
.valueMatches("errormessage",
"Request Header/s size is larger than permissible limit (.*). Request Header/s size for 'x-anyheader' is .*");
restClient.get()
.uri("/headers")
.header("test", "requestheadersize")
.header("X-AnyHeader", "111111111122222222223333333333444444444455555555556666666666")
.exchange()
.expectStatus()
.isOk();
}
public static final MediaType FORM_URL_ENCODED_CONTENT_TYPE = new MediaType(APPLICATION_FORM_URLENCODED,
@@ -469,7 +606,9 @@ public class ServerMvcIntegrationTests {
void multipartFormDataRestTemplateWorks() {
MultiValueMap<String, HttpEntity<?>> formData = createMultipartData();
RequestEntity<MultiValueMap<String, HttpEntity<?>>> request = RequestEntity.post("/post")
.contentType(MULTIPART_FORM_DATA).header("Host", "www.testform.org").body(formData);
.contentType(MULTIPART_FORM_DATA)
.header("Host", "www.testform.org")
.body(formData);
ResponseEntity<Map> response = restTemplate.exchange(request, Map.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertMultipartData(response.getBody());
@@ -477,8 +616,13 @@ public class ServerMvcIntegrationTests {
@Test
public void redirectToWorks() {
restClient.get().uri("/anything/redirect").exchange().expectStatus().isEqualTo(HttpStatus.MOVED_PERMANENTLY)
.expectHeader().valueEquals(HttpHeaders.LOCATION, "https://exampleredirect.com");
restClient.get()
.uri("/anything/redirect")
.exchange()
.expectStatus()
.isEqualTo(HttpStatus.MOVED_PERMANENTLY)
.expectHeader()
.valueEquals(HttpHeaders.LOCATION, "https://exampleredirect.com");
}
private MultiValueMap<String, HttpEntity<?>> createMultipartData() {
@@ -497,41 +641,65 @@ public class ServerMvcIntegrationTests {
@Test
public void removeRequestHeaderWorks() {
restClient.get().uri("/anything/removerequestheader").header("X-Request-Foo", "Bar").exchange().expectStatus()
.isOk().expectBody(Map.class).consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).doesNotContainKey("X-Request-Foo");
});
restClient.get()
.uri("/anything/removerequestheader")
.header("X-Request-Foo", "Bar")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> map = res.getResponseBody();
Map<String, Object> headers = getMap(map, "headers");
assertThat(headers).doesNotContainKey("X-Request-Foo");
});
}
@Test
public void setRequestHeaderWorks() {
restClient.get().uri("/headers").header("test", "setrequestheader").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).doesNotContainEntry("X-Test", "value1");
assertThat(headers).containsEntry("X-Test", "value2");
});
restClient.get()
.uri("/headers")
.header("test", "setrequestheader")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).doesNotContainEntry("X-Test", "value1");
assertThat(headers).containsEntry("X-Test", "value2");
});
}
@Test
public void setRequestHeaderHostWorks() {
restClient.get().uri("/headers").header("Host", "www.setrequesthostheader.org").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("Host", "otherhost.io");
});
restClient.get()
.uri("/headers")
.header("Host", "www.setrequesthostheader.org")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("Host", "otherhost.io");
});
}
@Test
public void setResponseHeaderWorks() {
restClient.get().uri("/anything/setresponseheader").header("test", "setresponseheader").exchange()
.expectStatus().isOk().expectBody(Map.class).consumeWith(res -> {
HttpHeaders headers = res.getResponseHeaders();
assertThat(headers).doesNotContainEntry("X-Test", List.of("value1"));
assertThat(headers).containsEntry("X-Test", List.of("value2"));
});
restClient.get()
.uri("/anything/setresponseheader")
.header("test", "setresponseheader")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
HttpHeaders headers = res.getResponseHeaders();
assertThat(headers).doesNotContainEntry("X-Test", List.of("value1"));
assertThat(headers).containsEntry("X-Test", List.of("value2"));
});
}
@Test
@@ -541,38 +709,70 @@ public class ServerMvcIntegrationTests {
}
private void testNestedRoute(String nestedPath) {
restClient.get().uri("/anything/nested/" + nestedPath).header("test", "nested").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Test", nestedPath);
});
restClient.get()
.uri("/anything/nested/" + nestedPath)
.header("test", "nested")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Test", nestedPath);
});
}
@Test
public void removeRequestParameterWorks() {
restClient.get().uri("/anything/removerequestparameter?foo=bar").header("test", "removerequestparam").exchange()
.expectStatus().isOk().expectHeader().doesNotExist("foo");
restClient.get()
.uri("/anything/removerequestparameter?foo=bar")
.header("test", "removerequestparam")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.doesNotExist("foo");
}
@Test
public void removeRequestParameterPostWorks() {
restClient.post().uri("/post?foo=bar").bodyValue("hello").header("Host", "www.removerequestparampost.org")
.exchange().expectStatus().isOk().expectHeader().doesNotExist("foo").expectBody(Map.class)
.consumeWith(res -> {
assertThat(res.getResponseBody()).containsEntry("data", "hello");
});
restClient.post()
.uri("/post?foo=bar")
.bodyValue("hello")
.header("Host", "www.removerequestparampost.org")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.doesNotExist("foo")
.expectBody(Map.class)
.consumeWith(res -> {
assertThat(res.getResponseBody()).containsEntry("data", "hello");
});
}
@Test
public void removeResponseHeaderWorks() {
restClient.get().uri("/anything/removeresponseheader").header("test", "removeresponseheader").exchange()
.expectStatus().isOk().expectHeader().doesNotExist("X-Test");
restClient.get()
.uri("/anything/removeresponseheader")
.header("test", "removeresponseheader")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.doesNotExist("X-Test");
}
@Test
public void rewriteResponseHeaderWorks() {
restClient.get().uri("/headers").header("test", "rewriteresponseheader").exchange().expectStatus().isOk()
.expectHeader().valueEquals("X-Request-Foo", "/42?user=ford&password=***&flag=true");
restClient.get()
.uri("/headers")
.header("test", "rewriteresponseheader")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-Request-Foo", "/42?user=ford&password=***&flag=true");
}
@Test
@@ -589,75 +789,126 @@ public class ServerMvcIntegrationTests {
@Test
public void mapRequestHeaderWorks() {
restClient.get().uri("/anything/maprequestheader").header("X-Foo", "fooval").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Bar", "fooval");
});
restClient.get()
.uri("/anything/maprequestheader")
.header("X-Foo", "fooval")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Bar", "fooval");
});
}
@Test
public void dedupeResponseHeaderWorks() {
restClient.get().uri("/headers").header("Host", "www.deduperesponseheader.org").exchange().expectStatus().isOk()
.expectHeader().valueEquals("Access-Control-Allow-Credentials", "true").expectHeader()
.valueEquals("Access-Control-Allow-Origin", "https://example.org").expectHeader()
.valueEquals("Scout-Cookie", "S'mores").expectHeader()
.valueEquals("Next-Week-Lottery-Numbers", "4", "2", "42");
restClient.get()
.uri("/headers")
.header("Host", "www.deduperesponseheader.org")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("Access-Control-Allow-Credentials", "true")
.expectHeader()
.valueEquals("Access-Control-Allow-Origin", "https://example.org")
.expectHeader()
.valueEquals("Scout-Cookie", "S'mores")
.expectHeader()
.valueEquals("Next-Week-Lottery-Numbers", "4", "2", "42");
}
@Test
public void addRequestHeadersIfNotPresentWorks() {
restClient.get().uri("/headers").header("Host", "www.addrequestheadersifnotpresent.org")
.header("X-Request-Beta", "Value1").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
// this asserts that Value2 was not added
assertThat(headers).containsEntry("X-Request-Beta", "Value1");
assertThat(headers).containsKey("X-Request-Acme");
List<String> values = (List<String>) headers.get("X-Request-Acme");
assertThat(values).hasSize(4).containsOnly("ValueX", "ValueY", "ValueZ", "www");
});
restClient.get()
.uri("/headers")
.header("Host", "www.addrequestheadersifnotpresent.org")
.header("X-Request-Beta", "Value1")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
// this asserts that Value2 was not added
assertThat(headers).containsEntry("X-Request-Beta", "Value1");
assertThat(headers).containsKey("X-Request-Acme");
List<String> values = (List<String>) headers.get("X-Request-Acme");
assertThat(values).hasSize(4).containsOnly("ValueX", "ValueY", "ValueZ", "www");
});
}
@Test
public void rewriteLocationResponseHeaderWorks() {
restClient.get().uri("/anything/rewritelocationresponseheader")
.header("Host", "test1.rewritelocationresponseheader.org").exchange().expectStatus().isOk()
.expectHeader()
.valueEquals("Location", "https://test1.rewritelocationresponseheader.org/some/object/id");
restClient.get()
.uri("/anything/rewritelocationresponseheader")
.header("Host", "test1.rewritelocationresponseheader.org")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("Location", "https://test1.rewritelocationresponseheader.org/some/object/id");
}
@Test
public void readBodyWorks() {
Event messageEvent = new Event("message", "bar");
restClient.post().uri("/events").bodyValue(messageEvent).exchange().expectStatus().isOk().expectHeader()
.valueEquals("X-Foo", "message").expectBody(Event.class)
.consumeWith(res -> assertThat(res.getResponseBody()).isEqualTo(messageEvent));
restClient.post()
.uri("/events")
.bodyValue(messageEvent)
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-Foo", "message")
.expectBody(Event.class)
.consumeWith(res -> assertThat(res.getResponseBody()).isEqualTo(messageEvent));
Event messageChannelEvent = new Event("message.channel", "baz");
restClient.post().uri("/events").bodyValue(messageChannelEvent).exchange().expectStatus().isOk().expectHeader()
.valueEquals("X-Channel-Foo", "message.channel").expectBody(Event.class)
.consumeWith(res -> assertThat(res.getResponseBody()).isEqualTo(messageChannelEvent));
restClient.post()
.uri("/events")
.bodyValue(messageChannelEvent)
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-Channel-Foo", "message.channel")
.expectBody(Event.class)
.consumeWith(res -> assertThat(res.getResponseBody()).isEqualTo(messageChannelEvent));
}
@Test
@SuppressWarnings("unchecked")
public void rewriteRequestBodyStringWorks() {
restClient.post().uri("/post").header("Host", "www.modifyrequestbodystring.org").bodyValue("hello").exchange()
.expectStatus().isOk().expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("data", "HELLOHELLO"));
restClient.post()
.uri("/post")
.header("Host", "www.modifyrequestbodystring.org")
.bodyValue("hello")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("data", "HELLOHELLO"));
}
@Test
@SuppressWarnings("unchecked")
public void rewriteRequestBodyObjectWorks() {
restClient.post().uri("/post").header("Host", "www.modifyrequestbodyobject.org").bodyValue("hello world")
.exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("data",
"{\"message\":\"HELLO WORLD\"}"));
restClient.post()
.uri("/post")
.header("Host", "www.modifyrequestbodyobject.org")
.bodyValue("hello world")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(result -> assertThat(result.getResponseBody()).containsEntry("data",
"{\"message\":\"HELLO WORLD\"}"));
}
@Test
@@ -667,45 +918,66 @@ public class ServerMvcIntegrationTests {
@Test
public void forwardNon200StatusWorks() {
restClient.get().uri("/doforward2").exchange().expectStatus().isCreated().expectBody(String.class)
.isEqualTo("hello2");
restClient.get()
.uri("/doforward2")
.exchange()
.expectStatus()
.isCreated()
.expectBody(String.class)
.isEqualTo("hello2");
}
@Test
@SuppressWarnings("rawtypes")
public void queryParamWorks() {
restClient.get().uri("/get?foo=bar").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(result -> {
Map responseBody = result.getResponseBody();
assertThat(responseBody).containsKey("args");
Map args = getMap(responseBody, "args");
assertThat(args).containsKey("foo");
assertThat(args.get("foo")).isEqualTo("bar");
});
restClient.get()
.uri("/get?foo=bar")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(result -> {
Map responseBody = result.getResponseBody();
assertThat(responseBody).containsKey("args");
Map args = getMap(responseBody, "args");
assertThat(args).containsKey("foo");
assertThat(args.get("foo")).isEqualTo("bar");
});
}
@SuppressWarnings("rawtypes")
@Test
public void queryParamWithSpecialCharactersWorks() {
restClient.get().uri("/get?myparam= &intlparam=æøå").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(result -> {
Map responseBody = result.getResponseBody();
assertThat(responseBody).containsKey("args");
Map args = getMap(responseBody, "args");
assertThat(args).containsKey("myparam");
assertThat(args.get("myparam")).isEqualTo(" ");
assertThat(args).containsKey("intlparam");
assertThat(args.get("intlparam")).isEqualTo("æøå");
});
restClient.get()
.uri("/get?myparam= &intlparam=æøå")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(result -> {
Map responseBody = result.getResponseBody();
assertThat(responseBody).containsKey("args");
Map args = getMap(responseBody, "args");
assertThat(args).containsKey("myparam");
assertThat(args.get("myparam")).isEqualTo(" ");
assertThat(args).containsKey("intlparam");
assertThat(args.get("intlparam")).isEqualTo("æøå");
});
}
@Test
public void clientResponseBodyAttributeWorks() {
restClient.get().uri("/anything/readresponsebody").header("X-Foo", "fooval").exchange().expectStatus().isOk()
.expectBody(Map.class).consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Foo", "FOOVAL");
});
restClient.get()
.uri("/anything/readresponsebody")
.header("X-Foo", "fooval")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Foo", "FOOVAL");
});
}
@SpringBootConfiguration
@@ -742,7 +1014,7 @@ public class ServerMvcIntegrationTests {
@Bean
public RouterFunction<ServerResponse> nonGatewayRouterFunctions2() {
return route(GET("/hello2"), request -> ServerResponse.status(HttpStatus.CREATED).body("hello2"))
.withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, "hello2");
.withAttribute(MvcUtils.GATEWAY_ROUTE_ID_ATTR, "hello2");
}
@Bean

View File

@@ -86,8 +86,10 @@ public class TokenRelayFilterFunctionsTests {
when(accessToken.getTokenValue()).thenReturn("mytoken");
ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("myregistrationid")
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).clientId("myclientid")
.tokenUri("mytokenuri").build();
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.clientId("myclientid")
.tokenUri("mytokenuri")
.build();
OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(clientRegistration, "joe", accessToken);
when(authorizedClientManager.authorize(any(OAuth2AuthorizeRequest.class))).thenReturn(authorizedClient);

View File

@@ -56,10 +56,17 @@ public class VanillaRouterFunctionTests {
@SuppressWarnings("rawtypes")
@Test
public void routerFunctionsRouteWorks() {
restClient.post().uri("/anything/routerfunctionsroute").header("Host", "www.routerfunctionsroute.org")
.bodyValue("hello").exchange().expectStatus().isOk().expectBody(Map.class).consumeWith(result -> {
System.out.println();
});
restClient.post()
.uri("/anything/routerfunctionsroute")
.header("Host", "www.routerfunctionsroute.org")
.bodyValue("hello")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(result -> {
System.out.println();
});
}
@SpringBootConfiguration

View File

@@ -65,8 +65,8 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrarTests {
void contextLoads(ApplicationContext context) {
Map<String, RouterFunction> routerFunctions = getRouterFunctions(context);
assertThat(routerFunctions).hasSizeGreaterThanOrEqualTo(5).containsKeys("listRoute1", "route1",
"route2CustomId", "listRoute2", "listRoute3", "listRoute4");
assertThat(routerFunctions).hasSizeGreaterThanOrEqualTo(5)
.containsKeys("listRoute1", "route1", "route2CustomId", "listRoute2", "listRoute3", "listRoute4");
RouterFunction listRoute1RouterFunction = routerFunctions.get("listRoute1");
listRoute1RouterFunction.accept(new AbstractRouterFunctionsVisitor() {
@Override
@@ -152,7 +152,7 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrarTests {
public void attributes(Map<String, Object> attributes) {
if (attributes.containsKey("gatewayRouterFunctions")) {
Map<String, RouterFunction> map = (Map<String, RouterFunction>) attributes
.get("gatewayRouterFunctions");
.get("gatewayRouterFunctions");
routerFunctionsRef.compareAndSet(null, map);
}
}
@@ -165,21 +165,32 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrarTests {
@Test
@SuppressWarnings("unchecked")
public void configuredRouteWorks() {
restClient.get().uri("/anything/listRoute1").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Test", "listRoute1");
});
restClient.get()
.uri("/anything/listRoute1")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Test", "listRoute1");
});
}
@Test
@SuppressWarnings("unchecked")
public void lbRouteWorks() {
restClient.get().uri("/anything/listRoute3").header("MyHeaderName", "MyHeaderVal").exchange().expectStatus()
.isOk().expectBody(Map.class).consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Test", "listRoute3");
});
restClient.get()
.uri("/anything/listRoute3")
.header("MyHeaderName", "MyHeaderVal")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Test", "listRoute3");
});
}
@Test
@@ -187,21 +198,28 @@ public class GatewayMvcPropertiesBeanDefinitionRegistrarTests {
void refreshWorks(ConfigurableApplicationContext context) {
Map<String, RouterFunction> routerFunctions = getRouterFunctions(context);
assertThat(routerFunctions).hasSize(6);
TestPropertyValues.of("spring.cloud.gateway.mvc.routesMap.route3.uri=https://example3.com",
"spring.cloud.gateway.mvc.routesMap.route3.predicates[0].name=Path",
"spring.cloud.gateway.mvc.routesMap.route3.predicates[0].args.pattern=/anything/mapRoute3",
"spring.cloud.gateway.mvc.routesMap.route3.filters[0].Name=HttpbinUriResolver",
"spring.cloud.gateway.mvc.routesMap.route3.filters[1].Name=AddRequestHeader",
"spring.cloud.gateway.mvc.routesMap.route3.filters[1].args.name=X-Test",
"spring.cloud.gateway.mvc.routesMap.route3.filters[1].args.values=mapRoute3").applyTo(context);
TestPropertyValues
.of("spring.cloud.gateway.mvc.routesMap.route3.uri=https://example3.com",
"spring.cloud.gateway.mvc.routesMap.route3.predicates[0].name=Path",
"spring.cloud.gateway.mvc.routesMap.route3.predicates[0].args.pattern=/anything/mapRoute3",
"spring.cloud.gateway.mvc.routesMap.route3.filters[0].Name=HttpbinUriResolver",
"spring.cloud.gateway.mvc.routesMap.route3.filters[1].Name=AddRequestHeader",
"spring.cloud.gateway.mvc.routesMap.route3.filters[1].args.name=X-Test",
"spring.cloud.gateway.mvc.routesMap.route3.filters[1].args.values=mapRoute3")
.applyTo(context);
ContextRefresher contextRefresher = context.getBean(ContextRefresher.class);
contextRefresher.refresh();
// make http call before getRouterFunction()
restClient.get().uri("/anything/mapRoute3").exchange().expectStatus().isOk().expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Test", "mapRoute3");
});
restClient.get()
.uri("/anything/mapRoute3")
.exchange()
.expectStatus()
.isOk()
.expectBody(Map.class)
.consumeWith(res -> {
Map<String, Object> headers = getMap(res.getResponseBody(), "headers");
assertThat(headers).containsEntry("X-Test", "mapRoute3");
});
GatewayMvcProperties properties = context.getBean(GatewayMvcProperties.class);
assertThat(properties.getRoutesMap()).hasSize(3).containsKey("route3");

View File

@@ -55,7 +55,9 @@ public class ForwardedRequestHeadersFilterTests {
@Test
public void forwardedHeaderDoesNotExist() {
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get")
.remoteAddress("10.0.0.1:80").header(HttpHeaders.HOST, "myhost").buildRequest(null);
.remoteAddress("10.0.0.1:80")
.header(HttpHeaders.HOST, "myhost")
.buildRequest(null);
servletRequest.setRemoteHost("10.0.0.1");
ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList());
@@ -70,16 +72,17 @@ public class ForwardedRequestHeadersFilterTests {
assertThat(forwardeds).hasSize(1);
Forwarded forwarded = forwardeds.get(0);
assertThat(forwarded.getValues()).containsEntry("host", "myhost").containsEntry("proto", "http")
.containsEntry("for", "\"10.0.0.1:80\"");
assertThat(forwarded.getValues()).containsEntry("host", "myhost")
.containsEntry("proto", "http")
.containsEntry("for", "\"10.0.0.1:80\"");
}
@Test
public void forwardedHeaderExists() {
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get")
.remoteAddress("10.0.0.1:80")
.header(FORWARDED_HEADER, "for=12.34.56.78;host=example.com;proto=https; for=23.45.67.89")
.buildRequest(null);
.remoteAddress("10.0.0.1:80")
.header(FORWARDED_HEADER, "for=12.34.56.78;host=example.com;proto=https; for=23.45.67.89")
.buildRequest(null);
servletRequest.setRemoteHost("10.0.0.1");
ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList());
@@ -95,17 +98,18 @@ public class ForwardedRequestHeadersFilterTests {
Forwarded addedForwardedHeader = forwardeds.get(0);
Forwarded existingForwardedHeader = forwardeds.get(1);
assertThat(existingForwardedHeader.getValues()).containsEntry("proto", "http").containsEntry("for",
"\"10.0.0.1:80\"");
assertThat(existingForwardedHeader.getValues()).containsEntry("proto", "http")
.containsEntry("for", "\"10.0.0.1:80\"");
assertThat(addedForwardedHeader.getValues()).containsEntry("proto", "https").containsEntry("for",
"23.45.67.89");
assertThat(addedForwardedHeader.getValues()).containsEntry("proto", "https")
.containsEntry("for", "23.45.67.89");
}
@Test
public void noHostHeader() throws UnknownHostException {
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get")
.remoteAddress("10.0.0.1:80").buildRequest(null);
.remoteAddress("10.0.0.1:80")
.buildRequest(null);
servletRequest.setRemoteHost("10.0.0.1");
ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList());
@@ -126,7 +130,9 @@ public class ForwardedRequestHeadersFilterTests {
@Test
public void correctIPv6RemoteAddressMapping() throws UnknownHostException {
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get")
.remoteAddress("2001:db8:cafe:0:0:0:0:17:80").header(HttpHeaders.HOST, "myhost").buildRequest(null);
.remoteAddress("2001:db8:cafe:0:0:0:0:17:80")
.header(HttpHeaders.HOST, "myhost")
.buildRequest(null);
servletRequest.setRemoteHost("2001:db8:cafe:0:0:0:0:17");
ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList());
@@ -147,7 +153,8 @@ public class ForwardedRequestHeadersFilterTests {
@Test
public void unresolvedRemoteAddressFallsBackToHostName() throws UnknownHostException {
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.get("http://localhost/get")
.remoteAddress("unresolvable-hostname:80").buildRequest(null);
.remoteAddress("unresolvable-hostname:80")
.buildRequest(null);
servletRequest.setRemoteHost("unresolvable-hostname");
ServerRequest request = ServerRequest.create(servletRequest, Collections.emptyList());
@@ -162,8 +169,8 @@ public class ForwardedRequestHeadersFilterTests {
assertThat(forwardeds).hasSize(1);
Forwarded forwarded = forwardeds.get(0);
assertThat(forwarded.getValues()).containsEntry("proto", "http").containsEntry("for",
"\"unresolvable-hostname:80\"");
assertThat(forwarded.getValues()).containsEntry("proto", "http")
.containsEntry("for", "\"unresolvable-hostname:80\"");
}
@Test

View File

@@ -32,7 +32,8 @@ public class TransferEncodingNormalizationRequestHeadersFilterTests {
@Test
public void noTransferEncodingWithContentLength() {
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.post("http://localhost/post")
.header(HttpHeaders.CONTENT_LENGTH, "6").buildRequest(null);
.header(HttpHeaders.CONTENT_LENGTH, "6")
.buildRequest(null);
HttpHeaders headers = testFilter(ServerRequest.create(servletRequest, Collections.emptyList()));
assertThat(headers).containsKey(HttpHeaders.CONTENT_LENGTH).doesNotContainKey(HttpHeaders.TRANSFER_ENCODING);
@@ -41,8 +42,9 @@ public class TransferEncodingNormalizationRequestHeadersFilterTests {
@Test
public void transferEncodingWithContentLength() {
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.post("http://localhost/post")
.header(HttpHeaders.CONTENT_LENGTH, "6").header(HttpHeaders.TRANSFER_ENCODING, "chunked")
.buildRequest(null);
.header(HttpHeaders.CONTENT_LENGTH, "6")
.header(HttpHeaders.TRANSFER_ENCODING, "chunked")
.buildRequest(null);
HttpHeaders headers = testFilter(ServerRequest.create(servletRequest, Collections.emptyList()));
assertThat(headers).doesNotContainKey(HttpHeaders.CONTENT_LENGTH).containsKey(HttpHeaders.TRANSFER_ENCODING);
@@ -51,8 +53,9 @@ public class TransferEncodingNormalizationRequestHeadersFilterTests {
@Test
public void transferEncodingCaseInsensitiveWithContentLength() {
MockHttpServletRequest servletRequest = MockMvcRequestBuilders.post("http://localhost/post")
.header(HttpHeaders.CONTENT_LENGTH, "6").header(HttpHeaders.TRANSFER_ENCODING, "Chunked ")
.buildRequest(null);
.header(HttpHeaders.CONTENT_LENGTH, "6")
.header(HttpHeaders.TRANSFER_ENCODING, "Chunked ")
.buildRequest(null);
HttpHeaders headers = testFilter(ServerRequest.create(servletRequest, Collections.emptyList()));
assertThat(headers).doesNotContainKey(HttpHeaders.CONTENT_LENGTH).containsKey(HttpHeaders.TRANSFER_ENCODING);

View File

@@ -64,16 +64,28 @@ public class WeightRequestPredicateIntegrationTests {
public void highWeight() {
filter.setRandomSupplier(getRandom(0.9));
testClient.get().uri("/get").header(HttpHeaders.HOST, "www.weight-high.org").exchange().expectStatus().isOk()
.expectHeader().valueEquals("X-Route", "weight_high_test");
testClient.get()
.uri("/get")
.header(HttpHeaders.HOST, "www.weight-high.org")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-Route", "weight_high_test");
}
@Test
public void lowWeight() {
filter.setRandomSupplier(getRandom(0.1));
testClient.get().uri("/get").header(HttpHeaders.HOST, "www.weight-low.org").exchange().expectStatus().isOk()
.expectHeader().valueEquals("X-Route", "weight_low_test");
testClient.get()
.uri("/get")
.header(HttpHeaders.HOST, "www.weight-low.org")
.exchange()
.expectStatus()
.isOk()
.expectHeader()
.valueEquals("X-Route", "weight_low_test");
}
@EnableAutoConfiguration

View File

@@ -49,7 +49,7 @@ public class HttpbinTestcontainers implements ApplicationContextInitializer<Conf
public static GenericContainer<?> createContainer() {
return new GenericContainer<>(DEFAULT_IMAGE_NAME).withExposedPorts(DEFAULT_PORT)
.waitingFor(new HttpWaitStrategy().forPort(DEFAULT_PORT));
.waitingFor(new HttpWaitStrategy().forPort(DEFAULT_PORT));
}
@Override

View File

@@ -569,7 +569,8 @@ public class DefaultTestRestClient implements TestRestClient {
return "";
}
Charset charset = Optional.ofNullable(this.result.getResponseHeaders().getContentType())
.map(MimeType::getCharset).orElse(StandardCharsets.UTF_8);
.map(MimeType::getCharset)
.orElse(StandardCharsets.UTF_8);
return new String(body, charset);
}

View File

@@ -264,8 +264,10 @@ public class ExchangeResult {
}
private String formatHeaders(HttpHeaders headers, String delimiter) {
return headers.entrySet().stream().map(entry -> entry.getKey() + ": " + entry.getValue())
.collect(Collectors.joining(delimiter));
return headers.entrySet()
.stream()
.map(entry -> entry.getKey() + ": " + entry.getValue())
.collect(Collectors.joining(delimiter));
}
@Nullable

View File

@@ -124,10 +124,10 @@ public class HeaderAssertions {
this.exchangeResult.assertWithDiagnostics(() -> {
List<String> values = getRequiredValues(name);
AssertionErrors
.assertTrue(
getMessage(name) + " has fewer or more values " + values
+ " than number of patterns to match with " + Arrays.toString(patterns),
values.size() == patterns.length);
.assertTrue(
getMessage(name) + " has fewer or more values " + values
+ " than number of patterns to match with " + Arrays.toString(patterns),
values.size() == patterns.length);
for (int i = 0; i < values.size(); i++) {
String value = values.get(i);
String pattern = patterns[i];

View File

@@ -150,7 +150,7 @@ public class StatusAssertions {
public TestRestClient.ResponseSpec reasonEquals(String reason) {
String actual = getReasonPhrase(this.exchangeResult.getStatus());
this.exchangeResult
.assertWithDiagnostics(() -> AssertionErrors.assertEquals("Response status reason", reason, actual));
.assertWithDiagnostics(() -> AssertionErrors.assertEquals("Response status reason", reason, actual));
return this.responseSpec;
}

View File

@@ -180,8 +180,12 @@ public class XpathAssertions {
}
private String getCharset() {
return Optional.of(this.bodySpec.returnResult()).map(EntityExchangeResult::getResponseHeaders)
.map(HttpHeaders::getContentType).map(MimeType::getCharset).orElse(StandardCharsets.UTF_8).name();
return Optional.of(this.bodySpec.returnResult())
.map(EntityExchangeResult::getResponseHeaders)
.map(HttpHeaders::getContentType)
.map(MimeType::getCharset)
.orElse(StandardCharsets.UTF_8)
.name();
}
@Override

View File

@@ -120,35 +120,43 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
getAvailableEndpointsForClass(AbstractGatewayControllerEndpoint.class.getName()),
getAvailableEndpointsForClass(GatewayControllerEndpoint.class.getName()));
return Flux.fromIterable(endpoints).map(p -> p)
.flatMap(path -> this.routeLocator.getRoutes().map(r -> generateHref(r, path)).distinct().collectList()
.flatMapMany(Flux::fromIterable))
.distinct() // Ensure overall uniqueness
.collectList();
return Flux.fromIterable(endpoints)
.map(p -> p)
.flatMap(path -> this.routeLocator.getRoutes()
.map(r -> generateHref(r, path))
.distinct()
.collectList()
.flatMapMany(Flux::fromIterable))
.distinct() // Ensure overall uniqueness
.collectList();
}
private List<GatewayEndpointInfo> mergeEndpoints(List<GatewayEndpointInfo> listA, List<GatewayEndpointInfo> listB) {
Map<String, List<String>> mergedMap = new HashMap<>();
Stream.concat(listA.stream(), listB.stream()).forEach(e -> mergedMap
.computeIfAbsent(e.getHref(), k -> new ArrayList<>()).addAll(Arrays.asList(e.getMethods())));
Stream.concat(listA.stream(), listB.stream())
.forEach(e -> mergedMap.computeIfAbsent(e.getHref(), k -> new ArrayList<>())
.addAll(Arrays.asList(e.getMethods())));
return mergedMap.entrySet().stream().map(entry -> new GatewayEndpointInfo(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
return mergedMap.entrySet()
.stream()
.map(entry -> new GatewayEndpointInfo(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
private List<GatewayEndpointInfo> getAvailableEndpointsForClass(String className) {
try {
MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader(className);
Set<MethodMetadata> annotatedMethods = metadataReader.getAnnotationMetadata()
.getAnnotatedMethods(RequestMapping.class.getName());
.getAnnotatedMethods(RequestMapping.class.getName());
String gatewayActuatorPath = webEndpointProperties.getBasePath() + "/gateway";
return annotatedMethods.stream().map(method -> new GatewayEndpointInfo(gatewayActuatorPath
+ ((String[]) method.getAnnotationAttributes(RequestMapping.class.getName()).get("path"))[0],
((RequestMethod[]) method.getAnnotationAttributes(RequestMapping.class.getName()).get("method"))[0]
.name()))
.collect(Collectors.toList());
return annotatedMethods.stream()
.map(method -> new GatewayEndpointInfo(gatewayActuatorPath
+ ((String[]) method.getAnnotationAttributes(RequestMapping.class.getName()).get("path"))[0],
((RequestMethod[]) method.getAnnotationAttributes(RequestMapping.class.getName())
.get("method"))[0].name()))
.collect(Collectors.toList());
}
catch (IOException exception) {
log.warn(exception.getMessage());
@@ -186,8 +194,9 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
}
private Map<String, Object> convertToMap(List<String> byMetadata) {
return byMetadata.stream().map(keyValueStr -> keyValueStr.split(":"))
.collect(Collectors.toMap(kv -> kv[0], kv -> kv.length > 1 ? kv[1] : null));
return byMetadata.stream()
.map(keyValueStr -> keyValueStr.split(":"))
.collect(Collectors.toMap(kv -> kv[0], kv -> kv.length > 1 ? kv[1] : null));
}
@GetMapping("/globalfilters")
@@ -228,13 +237,14 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
@SuppressWarnings("unchecked")
public Mono<ResponseEntity<Object>> save(@PathVariable String id, @RequestBody RouteDefinition route) {
return Mono.just(route).doOnNext(this::validateRouteDefinition)
.flatMap(routeDefinition -> this.routeDefinitionWriter.save(Mono.just(routeDefinition).map(r -> {
r.setId(id);
log.debug("Saving route: " + route);
return r;
})).then(Mono.defer(() -> Mono.just(ResponseEntity.created(URI.create("/routes/" + id)).build()))))
.switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.badRequest().build())));
return Mono.just(route)
.doOnNext(this::validateRouteDefinition)
.flatMap(routeDefinition -> this.routeDefinitionWriter.save(Mono.just(routeDefinition).map(r -> {
r.setId(id);
log.debug("Saving route: " + route);
return r;
})).then(Mono.defer(() -> Mono.just(ResponseEntity.created(URI.create("/routes/" + id)).build()))))
.switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.badRequest().build())));
}
@PostMapping("/routes")
@@ -246,11 +256,12 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
});
return Flux.fromIterable(routes)
.flatMap(routeDefinition -> this.routeDefinitionWriter.save(Mono.just(routeDefinition).map(r -> {
log.debug("Saving route: " + routeDefinition);
return r;
}))).then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
.switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.badRequest().build())));
.flatMap(routeDefinition -> this.routeDefinitionWriter.save(Mono.just(routeDefinition).map(r -> {
log.debug("Saving route: " + routeDefinition);
return r;
})))
.then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build())))
.switchIfEmpty(Mono.defer(() -> Mono.just(ResponseEntity.badRequest().build())));
}
private void validateRouteId(RouteDefinition routeDefinition) {
@@ -260,11 +271,17 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
}
private void validateRouteDefinition(RouteDefinition routeDefinition) {
Set<String> unavailableFilterDefinitions = routeDefinition.getFilters().stream().filter(rd -> !isAvailable(rd))
.map(FilterDefinition::getName).collect(Collectors.toSet());
Set<String> unavailableFilterDefinitions = routeDefinition.getFilters()
.stream()
.filter(rd -> !isAvailable(rd))
.map(FilterDefinition::getName)
.collect(Collectors.toSet());
Set<String> unavailablePredicatesDefinitions = routeDefinition.getPredicates().stream()
.filter(rd -> !isAvailable(rd)).map(PredicateDefinition::getName).collect(Collectors.toSet());
Set<String> unavailablePredicatesDefinitions = routeDefinition.getPredicates()
.stream()
.filter(rd -> !isAvailable(rd))
.map(PredicateDefinition::getName)
.collect(Collectors.toSet());
if (!unavailableFilterDefinitions.isEmpty()) {
handleUnavailableDefinition(FilterDefinition.class.getSimpleName(), unavailableFilterDefinitions);
}
@@ -298,12 +315,12 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
private boolean isAvailable(FilterDefinition filterDefinition) {
return GatewayFilters.stream()
.anyMatch(gatewayFilterFactory -> filterDefinition.getName().equals(gatewayFilterFactory.name()));
.anyMatch(gatewayFilterFactory -> filterDefinition.getName().equals(gatewayFilterFactory.name()));
}
private boolean isAvailable(PredicateDefinition predicateDefinition) {
return routePredicates.stream()
.anyMatch(routePredicate -> predicateDefinition.getName().equals(routePredicate.name()));
.anyMatch(routePredicate -> predicateDefinition.getName().equals(routePredicate.name()));
}
@DeleteMapping("/routes/{id}")
@@ -317,8 +334,9 @@ public class AbstractGatewayControllerEndpoint implements ApplicationEventPublis
@GetMapping("/routes/{id}/combinedfilters")
public Mono<HashMap<String, Object>> combinedfilters(@PathVariable String id) {
// TODO: missing global filters
return this.routeLocator.getRoutes().filter(route -> route.getId().equals(id)).reduce(new HashMap<>(),
this::putItem);
return this.routeLocator.getRoutes()
.filter(route -> route.getId().equals(id))
.reduce(new HashMap<>(), this::putItem);
}
}

View File

@@ -56,7 +56,7 @@ public class GatewayLegacyControllerEndpoint extends AbstractGatewayControllerEn
@GetMapping("/routes")
public Mono<List<Map<String, Object>>> routes() {
Mono<Map<String, RouteDefinition>> routeDefs = this.routeDefinitionLocator.getRouteDefinitions()
.collectMap(RouteDefinition::getId);
.collectMap(RouteDefinition::getId);
Mono<List<Route>> routes = this.routeLocator.getRoutes().collectList();
return Mono.zip(routeDefs, routes).map(tuple -> {
Map<String, RouteDefinition> defs = tuple.getT1();
@@ -103,8 +103,11 @@ public class GatewayLegacyControllerEndpoint extends AbstractGatewayControllerEn
@GetMapping("/routes/{id}")
public Mono<ResponseEntity<RouteDefinition>> route(@PathVariable String id) {
// TODO: missing RouteLocator
return this.routeDefinitionLocator.getRouteDefinitions().filter(route -> route.getId().equals(id))
.singleOrEmpty().map(ResponseEntity::ok).switchIfEmpty(Mono.just(ResponseEntity.notFound().build()));
return this.routeDefinitionLocator.getRouteDefinitions()
.filter(route -> route.getId().equals(id))
.singleOrEmpty()
.map(ResponseEntity::ok)
.switchIfEmpty(Mono.just(ResponseEntity.notFound().build()));
}
}

View File

@@ -87,7 +87,7 @@ public abstract class AbstractSslConfigurer<T, S> {
try {
if (ssl.getKeyStore() != null && ssl.getKeyStore().length() > 0) {
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
char[] keyPassword = ssl.getKeyPassword() != null ? ssl.getKeyPassword().toCharArray() : null;
if (keyPassword == null && ssl.getKeyStorePassword() != null) {

View File

@@ -106,8 +106,9 @@ class ConfigurableHintsRegistrationProcessor implements BeanFactoryInitializatio
private static void addGenericsForClass(Set<Class<?>> genericsToAdd, ResolvableType resolvableType) {
if (resolvableType.getSuperType().hasGenerics()) {
genericsToAdd.addAll(Arrays.stream(resolvableType.getSuperType().getGenerics()).map(ResolvableType::toClass)
.collect(Collectors.toSet()));
genericsToAdd.addAll(Arrays.stream(resolvableType.getSuperType().getGenerics())
.map(ResolvableType::toClass)
.collect(Collectors.toSet()));
}
}

View File

@@ -356,7 +356,7 @@ public class GatewayAutoConfiguration {
public GrpcSslConfigurer grpcSslConfigurer(HttpClientProperties properties)
throws KeyStoreException, NoSuchAlgorithmException {
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(KeyStore.getInstance(KeyStore.getDefaultType()));
return new GrpcSslConfigurer(properties.getSsl());
@@ -792,7 +792,7 @@ public class GatewayAutoConfiguration {
HttpClient httpClient) {
Supplier<WebsocketClientSpec.Builder> builderSupplier = () -> {
WebsocketClientSpec.Builder builder = WebsocketClientSpec.builder()
.handlePing(properties.getWebsocket().isProxyPing());
.handlePing(properties.getWebsocket().isProxyPing());
if (properties.getWebsocket().getMaxFramePayloadLength() != null) {
builder.maxFramePayloadLength(properties.getWebsocket().getMaxFramePayloadLength());
}
@@ -886,19 +886,19 @@ class GatewayHints implements RuntimeHintsRegistrar {
return;
}
hints.reflection()
.registerType(TypeReference.of(FilterDefinition.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(PredicateDefinition.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(AbstractNameValueGatewayFilterFactory.NameValueConfig.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(
"org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator$DelegatingServiceInstance"),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS));
.registerType(TypeReference.of(FilterDefinition.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(PredicateDefinition.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference.of(AbstractNameValueGatewayFilterFactory.NameValueConfig.class),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.registerType(TypeReference
.of("org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator$DelegatingServiceInstance"),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS, MemberCategory.INVOKE_DECLARED_METHODS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS));
}
}

View File

@@ -27,8 +27,9 @@ public class GatewayEnvironmentPostProcessor implements EnvironmentPostProcessor
@Override
public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication application) {
env.getPropertySources().addFirst(new MapPropertySource("gateway-properties",
Collections.singletonMap("spring.webflux.hiddenmethod.filter.enabled", "false")));
env.getPropertySources()
.addFirst(new MapPropertySource("gateway-properties",
Collections.singletonMap("spring.webflux.hiddenmethod.filter.enabled", "false")));
}
}

View File

@@ -79,8 +79,10 @@ public class GatewayMetricsProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("enabled", enabled).append("prefix", prefix).append("tags", tags)
.toString();
return new ToStringCreator(this).append("enabled", enabled)
.append("prefix", prefix)
.append("tags", tags)
.toString();
}

View File

@@ -105,9 +105,11 @@ public class GatewayProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("routes", routes).append("defaultFilters", defaultFilters)
.append("streamingMediaTypes", streamingMediaTypes)
.append("failOnRouteDefinitionError", failOnRouteDefinitionError).toString();
return new ToStringCreator(this).append("routes", routes)
.append("defaultFilters", defaultFilters)
.append("streamingMediaTypes", streamingMediaTypes)
.append("failOnRouteDefinitionError", failOnRouteDefinitionError)
.toString();
}

View File

@@ -50,7 +50,10 @@ public class GatewayReactiveOAuth2AutoConfiguration {
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
.builder().authorizationCode().refreshToken().build();
.builder()
.authorizationCode()
.refreshToken()
.build();
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

View File

@@ -87,7 +87,7 @@ class GatewayRedisAutoConfiguration {
Jackson2JsonRedisSerializer<RouteDefinition> valueSerializer = new Jackson2JsonRedisSerializer<>(
RouteDefinition.class);
RedisSerializationContext.RedisSerializationContextBuilder<String, RouteDefinition> builder = RedisSerializationContext
.newSerializationContext(keySerializer);
.newSerializationContext(keySerializer);
RedisSerializationContext<String, RouteDefinition> context = builder.value(valueSerializer).build();
return new ReactiveRedisTemplate<>(factory, context);

View File

@@ -80,8 +80,8 @@ public class HttpClientFactory extends AbstractFactoryBean<HttpClient> {
ConnectionProvider connectionProvider = buildConnectionProvider(properties);
HttpClient httpClient = HttpClient.create(connectionProvider)
// TODO: move customizations to HttpClientCustomizers
.httpResponseDecoder(this::httpResponseDecoder);
// TODO: move customizations to HttpClientCustomizers
.httpResponseDecoder(this::httpResponseDecoder);
if (serverProperties.getHttp2().isEnabled()) {
httpClient = httpClient.protocol(HttpProtocol.HTTP11, HttpProtocol.H2);
@@ -170,13 +170,15 @@ public class HttpClientFactory extends AbstractFactoryBean<HttpClient> {
// create either Fixed or Elastic pool
ConnectionProvider.Builder builder = ConnectionProvider.builder(pool.getName());
if (pool.getType() == FIXED) {
builder.maxConnections(pool.getMaxConnections()).pendingAcquireMaxCount(-1)
.pendingAcquireTimeout(Duration.ofMillis(pool.getAcquireTimeout()));
builder.maxConnections(pool.getMaxConnections())
.pendingAcquireMaxCount(-1)
.pendingAcquireTimeout(Duration.ofMillis(pool.getAcquireTimeout()));
}
else {
// Elastic
builder.maxConnections(Integer.MAX_VALUE).pendingAcquireTimeout(Duration.ofMillis(0))
.pendingAcquireMaxCount(-1);
builder.maxConnections(Integer.MAX_VALUE)
.pendingAcquireTimeout(Duration.ofMillis(0))
.pendingAcquireMaxCount(-1);
}
if (pool.getMaxIdleTime() != null) {

View File

@@ -499,10 +499,11 @@ public class HttpClientProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("useInsecureTrustManager", useInsecureTrustManager)
.append("trustedX509Certificates", trustedX509Certificates)
.append("handshakeTimeout", handshakeTimeout)
.append("closeNotifyFlushTimeout", closeNotifyFlushTimeout)
.append("closeNotifyReadTimeout", closeNotifyReadTimeout).toString();
.append("trustedX509Certificates", trustedX509Certificates)
.append("handshakeTimeout", handshakeTimeout)
.append("closeNotifyFlushTimeout", closeNotifyFlushTimeout)
.append("closeNotifyReadTimeout", closeNotifyReadTimeout)
.toString();
}
}
@@ -534,7 +535,8 @@ public class HttpClientProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("maxFramePayloadLength", maxFramePayloadLength)
.append("proxyPing", proxyPing).toString();
.append("proxyPing", proxyPing)
.toString();
}
}

View File

@@ -68,9 +68,10 @@ public class HttpClientSslConfigurer extends AbstractSslConfigurer<HttpClient, H
}
});
sslContextSpec.sslContext(clientSslContext).handshakeTimeout(ssl.getHandshakeTimeout())
.closeNotifyFlushTimeout(ssl.getCloseNotifyFlushTimeout())
.closeNotifyReadTimeout(ssl.getCloseNotifyReadTimeout());
sslContextSpec.sslContext(clientSslContext)
.handshakeTimeout(ssl.getHandshakeTimeout())
.closeNotifyFlushTimeout(ssl.getCloseNotifyFlushTimeout())
.closeNotifyReadTimeout(ssl.getCloseNotifyReadTimeout());
}
}

View File

@@ -61,7 +61,7 @@ public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLoc
DiscoveryLocatorProperties properties) {
this(discoveryClient.getClass().getSimpleName(), properties);
serviceInstances = discoveryClient.getServices()
.flatMap(service -> discoveryClient.getInstances(service).collectList());
.flatMap(service -> discoveryClient.getInstances(service).collectList());
}
private DiscoveryClientRouteDefinitionLocator(String discoveryClientName, DiscoveryLocatorProperties properties) {
@@ -96,36 +96,39 @@ public class DiscoveryClientRouteDefinitionLocator implements RouteDefinitionLoc
};
}
return serviceInstances.filter(instances -> !instances.isEmpty()).flatMap(Flux::fromIterable)
.filter(includePredicate).collectMap(ServiceInstance::getServiceId)
// remove duplicates
.flatMapMany(map -> Flux.fromIterable(map.values())).map(instance -> {
RouteDefinition routeDefinition = buildRouteDefinition(urlExpr, instance);
return serviceInstances.filter(instances -> !instances.isEmpty())
.flatMap(Flux::fromIterable)
.filter(includePredicate)
.collectMap(ServiceInstance::getServiceId)
// remove duplicates
.flatMapMany(map -> Flux.fromIterable(map.values()))
.map(instance -> {
RouteDefinition routeDefinition = buildRouteDefinition(urlExpr, instance);
final ServiceInstance instanceForEval = new DelegatingServiceInstance(instance, properties);
final ServiceInstance instanceForEval = new DelegatingServiceInstance(instance, properties);
for (PredicateDefinition original : this.properties.getPredicates()) {
PredicateDefinition predicate = new PredicateDefinition();
predicate.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
predicate.addArg(entry.getKey(), value);
}
routeDefinition.getPredicates().add(predicate);
for (PredicateDefinition original : this.properties.getPredicates()) {
PredicateDefinition predicate = new PredicateDefinition();
predicate.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
predicate.addArg(entry.getKey(), value);
}
routeDefinition.getPredicates().add(predicate);
}
for (FilterDefinition original : this.properties.getFilters()) {
FilterDefinition filter = new FilterDefinition();
filter.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
filter.addArg(entry.getKey(), value);
}
routeDefinition.getFilters().add(filter);
for (FilterDefinition original : this.properties.getFilters()) {
FilterDefinition filter = new FilterDefinition();
filter.setName(original.getName());
for (Map.Entry<String, String> entry : original.getArgs().entrySet()) {
String value = getValueFromExpr(evalCtxt, parser, instanceForEval, entry);
filter.addArg(entry.getKey(), value);
}
routeDefinition.getFilters().add(filter);
}
return routeDefinition;
});
return routeDefinition;
});
}
protected RouteDefinition buildRouteDefinition(Expression urlExpr, ServiceInstance serviceInstance) {

View File

@@ -116,10 +116,14 @@ public class DiscoveryLocatorProperties {
@Override
public String toString() {
return new ToStringCreator(this).append("enabled", enabled).append("routeIdPrefix", routeIdPrefix)
.append("includeExpression", includeExpression).append("urlExpression", urlExpression)
.append("lowerCaseServiceId", lowerCaseServiceId).append("predicates", predicates)
.append("filters", filters).toString();
return new ToStringCreator(this).append("enabled", enabled)
.append("routeIdPrefix", routeIdPrefix)
.append("includeExpression", includeExpression)
.append("urlExpression", urlExpression)
.append("lowerCaseServiceId", lowerCaseServiceId)
.append("predicates", predicates)
.append("filters", filters)
.toString();
}
}

View File

@@ -72,8 +72,9 @@ public class GatewayMetricsFilter implements GlobalFilter, Ordered {
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
Sample sample = Timer.start(meterRegistry);
return chain.filter(exchange).doOnSuccess(aVoid -> endTimerRespectingCommit(exchange, sample))
.doOnError(throwable -> endTimerRespectingCommit(exchange, sample));
return chain.filter(exchange)
.doOnSuccess(aVoid -> endTimerRespectingCommit(exchange, sample))
.doOnError(throwable -> endTimerRespectingCommit(exchange, sample));
}
private void endTimerRespectingCommit(ServerWebExchange exchange, Sample sample) {

View File

@@ -76,7 +76,8 @@ public class LoadBalancerServiceInstanceCookieFilter implements GlobalFilter, Or
ServerWebExchange newExchange = exchange.mutate().request(exchange.getRequest().mutate().headers((headers) -> {
List<String> cookieHeaders = new ArrayList<>(headers.getOrEmpty(HttpHeaders.COOKIE));
String serviceInstanceCookie = new HttpCookie(instanceIdCookieName,
serviceInstanceResponse.getServer().getInstanceId()).toString();
serviceInstanceResponse.getServer().getInstanceId())
.toString();
cookieHeaders.add(serviceInstanceCookie);
headers.put(HttpHeaders.COOKIE, cookieHeaders);
}).build()).build();

View File

@@ -131,69 +131,69 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered {
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
Flux<HttpClientResponse> responseFlux = getHttpClientMono(route, exchange)
.flatMapMany(httpClient -> httpClient.headers(headers -> {
headers.add(httpHeaders);
// Will either be set below, or later by Netty
headers.remove(HttpHeaders.HOST);
if (preserveHost) {
String host = request.getHeaders().getFirst(HttpHeaders.HOST);
headers.add(HttpHeaders.HOST, host);
}
}).request(method).uri(url).send((req, nettyOutbound) -> {
if (log.isTraceEnabled()) {
nettyOutbound.withConnection(connection -> log.trace("outbound route: "
+ connection.channel().id().asShortText() + ", inbound: " + exchange.getLogPrefix()));
}
return nettyOutbound.send(request.getBody().map(this::getByteBuf));
}).responseConnection((res, connection) -> {
.flatMapMany(httpClient -> httpClient.headers(headers -> {
headers.add(httpHeaders);
// Will either be set below, or later by Netty
headers.remove(HttpHeaders.HOST);
if (preserveHost) {
String host = request.getHeaders().getFirst(HttpHeaders.HOST);
headers.add(HttpHeaders.HOST, host);
}
}).request(method).uri(url).send((req, nettyOutbound) -> {
if (log.isTraceEnabled()) {
nettyOutbound.withConnection(connection -> log.trace("outbound route: "
+ connection.channel().id().asShortText() + ", inbound: " + exchange.getLogPrefix()));
}
return nettyOutbound.send(request.getBody().map(this::getByteBuf));
}).responseConnection((res, connection) -> {
// Defer committing the response until all route filters have run
// Put client response as ServerWebExchange attribute and write
// response later NettyWriteResponseFilter
exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
exchange.getAttributes().put(CLIENT_RESPONSE_CONN_ATTR, connection);
// Defer committing the response until all route filters have run
// Put client response as ServerWebExchange attribute and write
// response later NettyWriteResponseFilter
exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
exchange.getAttributes().put(CLIENT_RESPONSE_CONN_ATTR, connection);
ServerHttpResponse response = exchange.getResponse();
// put headers and status so filters can modify the response
HttpHeaders headers = new HttpHeaders();
ServerHttpResponse response = exchange.getResponse();
// put headers and status so filters can modify the response
HttpHeaders headers = new HttpHeaders();
res.responseHeaders().forEach(entry -> headers.add(entry.getKey(), entry.getValue()));
res.responseHeaders().forEach(entry -> headers.add(entry.getKey(), entry.getValue()));
String contentTypeValue = headers.getFirst(HttpHeaders.CONTENT_TYPE);
if (StringUtils.hasLength(contentTypeValue)) {
exchange.getAttributes().put(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR, contentTypeValue);
}
String contentTypeValue = headers.getFirst(HttpHeaders.CONTENT_TYPE);
if (StringUtils.hasLength(contentTypeValue)) {
exchange.getAttributes().put(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR, contentTypeValue);
}
setResponseStatus(res, response);
setResponseStatus(res, response);
// make sure headers filters run after setting status so it is
// available in response
HttpHeaders filteredResponseHeaders = HttpHeadersFilter.filter(getHeadersFilters(), headers,
exchange, Type.RESPONSE);
// make sure headers filters run after setting status so it is
// available in response
HttpHeaders filteredResponseHeaders = HttpHeadersFilter.filter(getHeadersFilters(), headers, exchange,
Type.RESPONSE);
if (!filteredResponseHeaders.containsKey(HttpHeaders.TRANSFER_ENCODING)
&& filteredResponseHeaders.containsKey(HttpHeaders.CONTENT_LENGTH)) {
// It is not valid to have both the transfer-encoding header and
// the content-length header.
// Remove the transfer-encoding header in the response if the
// content-length header is present.
response.getHeaders().remove(HttpHeaders.TRANSFER_ENCODING);
}
if (!filteredResponseHeaders.containsKey(HttpHeaders.TRANSFER_ENCODING)
&& filteredResponseHeaders.containsKey(HttpHeaders.CONTENT_LENGTH)) {
// It is not valid to have both the transfer-encoding header and
// the content-length header.
// Remove the transfer-encoding header in the response if the
// content-length header is present.
response.getHeaders().remove(HttpHeaders.TRANSFER_ENCODING);
}
exchange.getAttributes().put(CLIENT_RESPONSE_HEADER_NAMES, filteredResponseHeaders.keySet());
exchange.getAttributes().put(CLIENT_RESPONSE_HEADER_NAMES, filteredResponseHeaders.keySet());
response.getHeaders().addAll(filteredResponseHeaders);
response.getHeaders().addAll(filteredResponseHeaders);
return Mono.just(res);
}));
return Mono.just(res);
}));
Duration responseTimeout = getResponseTimeout(route);
if (responseTimeout != null) {
responseFlux = responseFlux
.timeout(responseTimeout,
Mono.error(new TimeoutException("Response took longer than timeout: " + responseTimeout)))
.onErrorMap(TimeoutException.class,
th -> new ResponseStatusException(HttpStatus.GATEWAY_TIMEOUT, th.getMessage(), th));
.timeout(responseTimeout,
Mono.error(new TimeoutException("Response took longer than timeout: " + responseTimeout)))
.onErrorMap(TimeoutException.class,
th -> new ResponseStatusException(HttpStatus.GATEWAY_TIMEOUT, th.getMessage(), th));
}
return responseFlux.then(chain.filter(exchange));

View File

@@ -111,15 +111,15 @@ public class ReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {
URI requestUri = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
String serviceId = requestUri.getHost();
Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
.getSupportedLifecycleProcessors(clientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
.getSupportedLifecycleProcessors(clientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(new RequestDataContext(
new RequestData(exchange.getRequest(), exchange.getAttributes()), getHint(serviceId)));
return choose(lbRequest, serviceId, supportedLifecycleProcessors).doOnNext(response -> {
if (!response.hasServer()) {
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, response)));
.onComplete(new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, response)));
throw NotFoundException.create(properties.isUse404(), "Unable to find instance for " + url.getHost());
}
@@ -145,17 +145,18 @@ public class ReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
exchange.getAttributes().put(GATEWAY_LOADBALANCER_RESPONSE_ATTR, response);
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, response));
}).then(chain.filter(exchange))
.doOnError(throwable -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.FAILED, throwable, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR)))))
.doOnSuccess(aVoid -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.SUCCESS, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR),
new ResponseData(exchange.getResponse(),
new RequestData(exchange.getRequest(), exchange.getAttributes()))))));
})
.then(chain.filter(exchange))
.doOnError(throwable -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.FAILED, throwable, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR)))))
.doOnSuccess(aVoid -> supportedLifecycleProcessors.forEach(lifecycle -> lifecycle
.onComplete(new CompletionContext<ResponseData, ServiceInstance, RequestDataContext>(
CompletionContext.Status.SUCCESS, lbRequest,
exchange.getAttribute(GATEWAY_LOADBALANCER_RESPONSE_ATTR),
new ResponseData(exchange.getResponse(),
new RequestData(exchange.getRequest(), exchange.getAttributes()))))));
}
protected URI reconstructURI(ServiceInstance serviceInstance, URI original) {

View File

@@ -85,8 +85,12 @@ public class RouteToRequestUrlFilter implements GlobalFilter, Ordered {
}
URI mergedUrl = UriComponentsBuilder.fromUri(uri)
// .uri(routeUri)
.scheme(routeUri.getScheme()).host(routeUri.getHost()).port(routeUri.getPort()).build(encoded).toUri();
// .uri(routeUri)
.scheme(routeUri.getScheme())
.host(routeUri.getHost())
.port(routeUri.getPort())
.build(encoded)
.toUri();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, mergedUrl);
return chain.filter(exchange);
}

View File

@@ -106,17 +106,17 @@ public class WebClientHttpRoutingFilter implements GlobalFilter, Ordered {
}
return headersSpec.exchangeToMono(Mono::just)
// .log("webClient route")
.flatMap(res -> {
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().putAll(res.headers().asHttpHeaders());
response.setStatusCode(res.statusCode());
// Defer committing the response until all route filters have run
// Put client response as ServerWebExchange attribute and write
// response later NettyWriteResponseFilter
exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
return chain.filter(exchange);
});
// .log("webClient route")
.flatMap(res -> {
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().putAll(res.headers().asHttpHeaders());
response.setStatusCode(res.statusCode());
// Defer committing the response until all route filters have run
// Put client response as ServerWebExchange attribute and write
// response later NettyWriteResponseFilter
exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
return chain.filter(exchange);
});
}
private boolean requiresBody(HttpMethod method) {

View File

@@ -58,8 +58,8 @@ public class WebClientWriteResponseFilter implements GlobalFilter, Ordered {
ServerHttpResponse response = exchange.getResponse();
return response.writeWith(clientResponse.body(BodyExtractors.toDataBuffers()))
// .log("webClient response")
.doOnCancel(() -> cleanup(exchange));
// .log("webClient response")
.doOnCancel(() -> cleanup(exchange));
}));
}

View File

@@ -244,28 +244,32 @@ public class WebsocketRoutingFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> handle(WebSocketSession proxySession) {
Mono<Void> serverClose = proxySession.closeStatus().filter(__ -> session.isOpen())
.map(this::adaptCloseStatus).flatMap(session::close);
Mono<Void> proxyClose = session.closeStatus().filter(__ -> proxySession.isOpen())
.map(this::adaptCloseStatus).flatMap(proxySession::close);
Mono<Void> serverClose = proxySession.closeStatus()
.filter(__ -> session.isOpen())
.map(this::adaptCloseStatus)
.flatMap(session::close);
Mono<Void> proxyClose = session.closeStatus()
.filter(__ -> proxySession.isOpen())
.map(this::adaptCloseStatus)
.flatMap(proxySession::close);
// Use retain() for Reactor Netty
Mono<Void> proxySessionSend = proxySession
.send(session.receive().doOnNext(WebSocketMessage::retain).doOnNext(webSocketMessage -> {
if (log.isTraceEnabled()) {
log.trace("proxySession(send from client): " + proxySession.getId()
+ ", corresponding session:" + session.getId() + ", packet: "
+ webSocketMessage.getPayloadAsText());
}
}));
.send(session.receive().doOnNext(WebSocketMessage::retain).doOnNext(webSocketMessage -> {
if (log.isTraceEnabled()) {
log.trace("proxySession(send from client): " + proxySession.getId()
+ ", corresponding session:" + session.getId() + ", packet: "
+ webSocketMessage.getPayloadAsText());
}
}));
// .log("proxySessionSend", Level.FINE);
Mono<Void> serverSessionSend = session.send(
proxySession.receive().doOnNext(WebSocketMessage::retain).doOnNext(webSocketMessage -> {
if (log.isTraceEnabled()) {
log.trace("session(send from backend): " + session.getId()
+ ", corresponding proxySession:" + proxySession.getId() + " packet: "
+ webSocketMessage.getPayloadAsText());
}
}));
Mono<Void> serverSessionSend = session
.send(proxySession.receive().doOnNext(WebSocketMessage::retain).doOnNext(webSocketMessage -> {
if (log.isTraceEnabled()) {
log.trace("session(send from backend): " + session.getId()
+ ", corresponding proxySession:" + proxySession.getId() + " packet: "
+ webSocketMessage.getPayloadAsText());
}
}));
// .log("sessionSend", Level.FINE);
// Ensure closeStatus from one propagates to the other
Mono.when(serverClose, proxyClose).subscribe();

View File

@@ -315,8 +315,11 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli
@Override
public String toString() {
return new ToStringCreator(this).append("group", group).append("weights", weights)
.append("normalizedWeights", normalizedWeights).append("rangeIndexes", rangeIndexes).toString();
return new ToStringCreator(this).append("group", group)
.append("weights", weights)
.append("normalizedWeights", normalizedWeights)
.append("rangeIndexes", rangeIndexes)
.toString();
}
}

View File

@@ -106,17 +106,17 @@ public class CorsGatewayFilterApplicationListener implements ApplicationListener
final CorsConfiguration corsConfiguration = new CorsConfiguration();
findValue(corsMetadata, "allowCredentials")
.ifPresent(value -> corsConfiguration.setAllowCredentials((Boolean) value));
.ifPresent(value -> corsConfiguration.setAllowCredentials((Boolean) value));
findValue(corsMetadata, "allowedHeaders")
.ifPresent(value -> corsConfiguration.setAllowedHeaders(asList(value)));
.ifPresent(value -> corsConfiguration.setAllowedHeaders(asList(value)));
findValue(corsMetadata, "allowedMethods")
.ifPresent(value -> corsConfiguration.setAllowedMethods(asList(value)));
.ifPresent(value -> corsConfiguration.setAllowedMethods(asList(value)));
findValue(corsMetadata, "allowedOriginPatterns")
.ifPresent(value -> corsConfiguration.setAllowedOriginPatterns(asList(value)));
.ifPresent(value -> corsConfiguration.setAllowedOriginPatterns(asList(value)));
findValue(corsMetadata, "allowedOrigins")
.ifPresent(value -> corsConfiguration.setAllowedOrigins(asList(value)));
.ifPresent(value -> corsConfiguration.setAllowedOrigins(asList(value)));
findValue(corsMetadata, "exposedHeaders")
.ifPresent(value -> corsConfiguration.setExposedHeaders(asList(value)));
.ifPresent(value -> corsConfiguration.setExposedHeaders(asList(value)));
findValue(corsMetadata, "maxAge").ifPresent(value -> corsConfiguration.setMaxAge(asLong(value)));
return Optional.of(corsConfiguration);

View File

@@ -37,8 +37,10 @@ public class AddRequestHeaderGatewayFilterFactory extends AbstractNameValueGatew
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(httpHeaders -> httpHeaders.add(config.getName(), value)).build();
ServerHttpRequest request = exchange.getRequest()
.mutate()
.headers(httpHeaders -> httpHeaders.add(config.getName(), value))
.build();
return chain.filter(exchange.mutate().request(request).build());
}
@@ -46,7 +48,8 @@ public class AddRequestHeaderGatewayFilterFactory extends AbstractNameValueGatew
@Override
public String toString() {
return filterToStringCreator(AddRequestHeaderGatewayFilterFactory.this)
.append(config.getName(), config.getValue()).toString();
.append(config.getName(), config.getValue())
.toString();
}
};
}

View File

@@ -69,8 +69,11 @@ public class AddRequestHeadersIfNotPresentGatewayFilterFactory
for (Map.Entry<String, List<String>> kv : aggregatedHeaders.entrySet()) {
String headerName = kv.getKey();
boolean headerIsMissingOrBlank = exchange.getRequest().getHeaders().getOrEmpty(headerName).stream()
.allMatch(h -> !StringUtils.hasText(h));
boolean headerIsMissingOrBlank = exchange.getRequest()
.getHeaders()
.getOrEmpty(headerName)
.stream()
.allMatch(h -> !StringUtils.hasText(h));
if (headerIsMissingOrBlank) {
if (requestBuilder == null) {
@@ -78,9 +81,10 @@ public class AddRequestHeadersIfNotPresentGatewayFilterFactory
}
ServerWebExchange finalExchange = exchange;
requestBuilder.headers(httpHeaders -> {
List<String> replacedValues = kv.getValue().stream()
.map(value -> ServerWebExchangeUtils.expand(finalExchange, value))
.collect(Collectors.toList());
List<String> replacedValues = kv.getValue()
.stream()
.map(value -> ServerWebExchangeUtils.expand(finalExchange, value))
.collect(Collectors.toList());
httpHeaders.addAll(headerName, replacedValues);
});
}

View File

@@ -60,8 +60,10 @@ public class AddRequestParameterGatewayFilterFactory extends AbstractNameValueGa
boolean encoded = containsEncodedParts(uri);
try {
URI newUri = UriComponentsBuilder.fromUri(uri).replaceQuery(query.toString()).build(encoded)
.toUri();
URI newUri = UriComponentsBuilder.fromUri(uri)
.replaceQuery(query.toString())
.build(encoded)
.toUri();
ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build();
@@ -75,7 +77,8 @@ public class AddRequestParameterGatewayFilterFactory extends AbstractNameValueGa
@Override
public String toString() {
return filterToStringCreator(AddRequestParameterGatewayFilterFactory.this)
.append(config.getName(), config.getValue()).toString();
.append(config.getName(), config.getValue())
.toString();
}
};
}

View File

@@ -42,7 +42,8 @@ public class AddResponseHeaderGatewayFilterFactory extends AbstractNameValueGate
@Override
public String toString() {
return filterToStringCreator(AddResponseHeaderGatewayFilterFactory.this)
.append(config.getName(), config.getValue()).toString();
.append(config.getName(), config.getValue())
.toString();
}
};
}

View File

@@ -77,23 +77,23 @@ public class CacheRequestBodyGatewayFilterFactory
return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> {
final ServerRequest serverRequest = ServerRequest
.create(exchange.mutate().request(serverHttpRequest).build(), messageReaders);
.create(exchange.mutate().request(serverHttpRequest).build(), messageReaders);
return serverRequest.bodyToMono((config.getBodyClass())).doOnNext(objectValue -> {
Object previousCachedBody = exchange.getAttributes()
.put(ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR, objectValue);
.put(ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR, objectValue);
if (previousCachedBody != null) {
// store previous cached body
exchange.getAttributes().put(CACHED_ORIGINAL_REQUEST_BODY_BACKUP_ATTR, previousCachedBody);
}
}).then(Mono.defer(() -> {
ServerHttpRequest cachedRequest = exchange
.getAttribute(CACHED_SERVER_HTTP_REQUEST_DECORATOR_ATTR);
.getAttribute(CACHED_SERVER_HTTP_REQUEST_DECORATOR_ATTR);
Assert.notNull(cachedRequest, "cache request shouldn't be null");
exchange.getAttributes().remove(CACHED_SERVER_HTTP_REQUEST_DECORATOR_ATTR);
return chain.filter(exchange.mutate().request(cachedRequest).build()).doFinally(s -> {
//
Object backupCachedBody = exchange.getAttributes()
.get(CACHED_ORIGINAL_REQUEST_BODY_BACKUP_ATTR);
.get(CACHED_ORIGINAL_REQUEST_BODY_BACKUP_ATTR);
if (backupCachedBody instanceof DataBuffer dataBuffer) {
DataBufferUtils.release(dataBuffer);
}
@@ -105,7 +105,8 @@ public class CacheRequestBodyGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(CacheRequestBodyGatewayFilterFactory.this)
.append("Body class", config.getBodyClass()).toString();
.append("Body class", config.getBodyClass())
.toString();
}
};
}

View File

@@ -93,13 +93,14 @@ public class DedupeResponseHeaderGatewayFilterFactory
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> dedupe(exchange.getResponse().getHeaders(), config)));
.then(Mono.fromRunnable(() -> dedupe(exchange.getResponse().getHeaders(), config)));
}
@Override
public String toString() {
return filterToStringCreator(DedupeResponseHeaderGatewayFilterFactory.this)
.append(config.getName(), config.getStrategy()).toString();
.append(config.getName(), config.getStrategy())
.toString();
}
};
}

View File

@@ -107,7 +107,7 @@ public class JsonToGrpcGatewayFilterFactory
ServerWebExchangeUtils.setAlreadyRouted(exchange);
return modifiedResponse.writeWith(exchange.getRequest().getBody())
.then(chain.filter(exchange.mutate().response(modifiedResponse).build()));
.then(chain.filter(exchange.mutate().response(modifiedResponse).build()));
}
@Override
@@ -190,7 +190,7 @@ public class JsonToGrpcGatewayFilterFactory
Resource protoFile = resourceLoader.getResource(config.getProtoFile());
descriptor = DescriptorProtos.FileDescriptorProto.parseFrom(descriptorFile.getInputStream())
.getDescriptorForType();
.getDescriptorForType();
Descriptors.MethodDescriptor methodDescriptor = getMethodDescriptor(config,
descriptorFile.getInputStream());
@@ -218,19 +218,25 @@ public class JsonToGrpcGatewayFilterFactory
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
exchange.getResponse().getHeaders().set("Content-Type", "application/json");
return getDelegate().writeWith(deserializeJSONRequest().map(callGRPCServer()).map(serialiseGRPCResponse())
.map(wrapGRPCResponse()).cast(DataBuffer.class).last());
return getDelegate().writeWith(deserializeJSONRequest().map(callGRPCServer())
.map(serialiseGRPCResponse())
.map(wrapGRPCResponse())
.cast(DataBuffer.class)
.last());
}
private ClientCall<DynamicMessage, DynamicMessage> createClientCallForType(Config config,
Descriptors.ServiceDescriptor serviceDescriptor, Descriptors.Descriptor outputType) {
MethodDescriptor.Marshaller<DynamicMessage> marshaller = ProtoUtils
.marshaller(DynamicMessage.newBuilder(outputType).build());
.marshaller(DynamicMessage.newBuilder(outputType).build());
MethodDescriptor<DynamicMessage, DynamicMessage> methodDescriptor = MethodDescriptor
.<DynamicMessage, DynamicMessage>newBuilder().setType(MethodDescriptor.MethodType.UNKNOWN)
.setFullMethodName(MethodDescriptor.generateFullMethodName(serviceDescriptor.getFullName(),
config.getMethod()))
.setRequestMarshaller(marshaller).setResponseMarshaller(marshaller).build();
.<DynamicMessage, DynamicMessage>newBuilder()
.setType(MethodDescriptor.MethodType.UNKNOWN)
.setFullMethodName(
MethodDescriptor.generateFullMethodName(serviceDescriptor.getFullName(), config.getMethod()))
.setRequestMarshaller(marshaller)
.setResponseMarshaller(marshaller)
.build();
Channel channel = createChannel();
return channel.newCall(methodDescriptor, CallOptions.DEFAULT);
}
@@ -238,7 +244,7 @@ public class JsonToGrpcGatewayFilterFactory
private Descriptors.MethodDescriptor getMethodDescriptor(Config config, InputStream descriptorFile)
throws IOException, Descriptors.DescriptorValidationException {
DescriptorProtos.FileDescriptorSet fileDescriptorSet = DescriptorProtos.FileDescriptorSet
.parseFrom(descriptorFile);
.parseFrom(descriptorFile);
DescriptorProtos.FileDescriptorProto fileProto = fileDescriptorSet.getFile(0);
Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor.buildFrom(fileProto,
new Descriptors.FileDescriptor[0]);
@@ -250,8 +256,10 @@ public class JsonToGrpcGatewayFilterFactory
List<Descriptors.MethodDescriptor> methods = serviceDescriptor.getMethods();
return methods.stream().filter(method -> method.getName().equals(config.getMethod())).findFirst()
.orElseThrow(() -> new NoSuchElementException("No Method found"));
return methods.stream()
.filter(method -> method.getName().equals(config.getMethod()))
.findFirst()
.orElseThrow(() -> new NoSuchElementException("No Method found"));
}
private ManagedChannel createChannel() {
@@ -296,7 +304,7 @@ public class JsonToGrpcGatewayFilterFactory
return jsonResponse -> {
try {
return new NettyDataBufferFactory(new PooledByteBufAllocator())
.wrap(Objects.requireNonNull(new ObjectMapper().writeValueAsBytes(jsonResponse)));
.wrap(Objects.requireNonNull(new ObjectMapper().writeValueAsBytes(jsonResponse)));
}
catch (JsonProcessingException e) {
return new NettyDataBufferFactory(new PooledByteBufAllocator()).allocateBuffer();

View File

@@ -64,8 +64,10 @@ public class MapRequestHeaderGatewayFilterFactory
}
List<String> headerValues = exchange.getRequest().getHeaders().get(config.getFromHeader());
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(i -> i.addAll(config.getToHeader(), headerValues)).build();
ServerHttpRequest request = exchange.getRequest()
.mutate()
.headers(i -> i.addAll(config.getToHeader(), headerValues))
.build();
return chain.filter(exchange.mutate().request(request).build());
}

View File

@@ -92,7 +92,7 @@ public class PrefixPathGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(PrefixPathGatewayFilterFactory.this).append("prefix", config.getPrefix())
.toString();
.toString();
}
};
}

View File

@@ -102,8 +102,11 @@ public class RedirectToGatewayFilterFactory
String location;
if (includeRequestParams) {
location = UriComponentsBuilder.fromUri(uri).queryParams(exchange.getRequest().getQueryParams())
.build().toUri().toString();
location = UriComponentsBuilder.fromUri(uri)
.queryParams(exchange.getRequest().getQueryParams())
.build()
.toUri()
.toString();
}
else {
location = uri.toString();
@@ -126,7 +129,8 @@ public class RedirectToGatewayFilterFactory
status = httpStatus.getStatus().toString();
}
return filterToStringCreator(RedirectToGatewayFilterFactory.this).append(status, uri)
.append(INCLUDE_REQUEST_PARAMS_KEY, includeRequestParams).toString();
.append(INCLUDE_REQUEST_PARAMS_KEY, includeRequestParams)
.toString();
}
};
}

View File

@@ -139,7 +139,8 @@ public class RemoveJsonAttributesResponseBodyGatewayFilterFactory extends
@Override
public String toString() {
return new ToStringCreator(this).append("fieldList", fieldList)
.append("deleteRecursively", deleteRecursively).toString();
.append("deleteRecursively", deleteRecursively)
.toString();
}
}

View File

@@ -48,8 +48,10 @@ public class RemoveRequestHeaderGatewayFilterFactory
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(httpHeaders -> httpHeaders.remove(config.getName())).build();
ServerHttpRequest request = exchange.getRequest()
.mutate()
.headers(httpHeaders -> httpHeaders.remove(config.getName()))
.build();
return chain.filter(exchange.mutate().request(request).build());
}
@@ -57,7 +59,8 @@ public class RemoveRequestHeaderGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RemoveRequestHeaderGatewayFilterFactory.this)
.append("name", config.getName()).toString();
.append("name", config.getName())
.toString();
}
};
}

View File

@@ -58,7 +58,9 @@ public class RemoveRequestParameterGatewayFilterFactory
queryParams.remove(config.getName());
URI newUri = UriComponentsBuilder.fromUri(request.getURI())
.replaceQueryParams(unmodifiableMultiValueMap(queryParams)).build().toUri();
.replaceQueryParams(unmodifiableMultiValueMap(queryParams))
.build()
.toUri();
ServerHttpRequest updatedRequest = exchange.getRequest().mutate().uri(newUri).build();
@@ -68,7 +70,8 @@ public class RemoveRequestParameterGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RemoveRequestParameterGatewayFilterFactory.this)
.append("name", config.getName()).toString();
.append("name", config.getName())
.toString();
}
};
}

View File

@@ -48,13 +48,14 @@ public class RemoveResponseHeaderGatewayFilterFactory
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange)
.then(Mono.fromRunnable(() -> exchange.getResponse().getHeaders().remove(config.getName())));
.then(Mono.fromRunnable(() -> exchange.getResponse().getHeaders().remove(config.getName())));
}
@Override
public String toString() {
return filterToStringCreator(RemoveResponseHeaderGatewayFilterFactory.this)
.append("name", config.getName()).toString();
.append("name", config.getName())
.toString();
}
};
}

View File

@@ -83,8 +83,9 @@ public class RequestHeaderSizeGatewayFilterFactory
if (!longHeaders.isEmpty()) {
exchange.getResponse().setStatusCode(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE);
exchange.getResponse().getHeaders().add(errorHeaderName,
getErrorMessage(longHeaders, config.getMaxSize()));
exchange.getResponse()
.getHeaders()
.add(errorHeaderName, getErrorMessage(longHeaders, config.getMaxSize()));
return exchange.getResponse().setComplete();
}
@@ -95,7 +96,8 @@ public class RequestHeaderSizeGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RequestHeaderSizeGatewayFilterFactory.this)
.append("maxSize", config.getMaxSize()).toString();
.append("maxSize", config.getMaxSize())
.toString();
}
};
}
@@ -103,7 +105,7 @@ public class RequestHeaderSizeGatewayFilterFactory
private static String getErrorMessage(HashMap<String, Long> longHeaders, DataSize maxSize) {
StringBuilder msg = new StringBuilder(String.format(ERROR_PREFIX, maxSize));
longHeaders
.forEach((header, size) -> msg.append(String.format(ERROR, header, DataSize.of(size, DataUnit.BYTES))));
.forEach((header, size) -> msg.append(String.format(ERROR, header, DataSize.of(size, DataUnit.BYTES))));
return msg.toString();
}

View File

@@ -59,7 +59,8 @@ public class RequestHeaderToRequestUriGatewayFilterFactory
@Override
public String toString() {
return filterToStringCreator(RequestHeaderToRequestUriGatewayFilterFactory.this)
.append("name", config.getName()).toString();
.append("name", config.getName())
.toString();
}
};
}

View File

@@ -94,7 +94,7 @@ public class RequestRateLimiterGatewayFilterFactory
RateLimiter<Object> limiter = getOrDefault(config.rateLimiter, defaultRateLimiter);
boolean denyEmpty = getOrDefault(config.denyEmptyKey, this.denyEmptyKey);
HttpStatusHolder emptyKeyStatus = HttpStatusHolder
.parse(getOrDefault(config.emptyKeyStatus, this.emptyKeyStatusCode));
.parse(getOrDefault(config.emptyKeyStatus, this.emptyKeyStatusCode));
return (exchange, chain) -> resolver.resolve(exchange).defaultIfEmpty(EMPTY_KEY).flatMap(key -> {
if (EMPTY_KEY.equals(key)) {

Some files were not shown because too many files have changed in this diff Show More