Merge branch 'Fetsivalen-extend-set-status-filter'

This commit is contained in:
Spencer Gibb
2019-07-24 11:33:04 -04:00
3 changed files with 61 additions and 8 deletions

View File

@@ -1022,6 +1022,18 @@ spring:
In either case, the HTTP status of the response will be set to 401.
The SetStatus GatewayFilter can be configured to return the original HTTP status code from the proxied request in a header in the response. Header will be added to the response if configured using following property.
.application.yml
[source,yaml]
----
spring:
cloud:
gateway:
set-status:
original-status-header-name: original-http-status
----
=== StripPrefix GatewayFilter Factory
The StripPrefix GatewayFilter Factory takes one parameter, `parts`. The `parts` parameter indicated the number of parts in the path to strip from the request before sending it downstream.

View File

@@ -21,17 +21,21 @@ import java.util.List;
import reactor.core.publisher.Mono;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.support.HttpStatusHolder;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import static java.util.Collections.singletonList;
import static org.springframework.cloud.gateway.support.GatewayToStringStyler.filterToStringCreator;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setResponseStatus;
/**
* @author Spencer Gibb
*/
@ConfigurationProperties("spring.cloud.gateway.set-status")
public class SetStatusGatewayFilterFactory
extends AbstractGatewayFilterFactory<SetStatusGatewayFilterFactory.Config> {
@@ -40,6 +44,11 @@ public class SetStatusGatewayFilterFactory
*/
public static final String STATUS_KEY = "status";
/**
* The name of the header which contains http code of the proxied request.
*/
private String originalStatusHeaderName;
public SetStatusGatewayFilterFactory() {
super(Config.class);
}
@@ -68,7 +77,12 @@ public class SetStatusGatewayFilterFactory
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// check not really needed, since it is guarded in setStatusCode,
// but it's a good example
setResponseStatus(exchange, statusHolder);
HttpStatus statusCode = exchange.getResponse().getStatusCode();
boolean isStatusCodeUpdated = setResponseStatus(exchange, statusHolder);
if (isStatusCodeUpdated && originalStatusHeaderName != null) {
exchange.getResponse().getHeaders().set(originalStatusHeaderName,
singletonList(statusCode.value()).toString());
}
}));
}
@@ -80,6 +94,14 @@ public class SetStatusGatewayFilterFactory
};
}
public String getOriginalStatusHeaderName() {
return originalStatusHeaderName;
}
public void setOriginalStatusHeaderName(String originalStatusHeaderName) {
this.originalStatusHeaderName = originalStatusHeaderName;
}
public static class Config {
// TODO: relaxed HttpStatus converter

View File

@@ -16,9 +16,11 @@
package org.springframework.cloud.gateway.filter.factory;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -38,6 +40,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@@ -47,6 +50,9 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@DirtiesContext
public class SetStatusGatewayFilterFactoryTests extends BaseWebClientTests {
@Autowired
private SetStatusGatewayFilterFactory filterFactory;
@Test
public void setStatusIntWorks() {
setStatusStringTest("www.setstatusint.org", HttpStatus.UNAUTHORIZED);
@@ -57,11 +63,6 @@ public class SetStatusGatewayFilterFactoryTests extends BaseWebClientTests {
setStatusStringTest("www.setstatusstring.org", HttpStatus.BAD_REQUEST);
}
private void setStatusStringTest(String host, HttpStatus status) {
testClient.get().uri("/headers").header("Host", host).exchange().expectStatus()
.isEqualTo(status);
}
@Test
public void nonStandardCodeWorks() {
HttpHeaders headers = new HttpHeaders();
@@ -78,6 +79,15 @@ public class SetStatusGatewayFilterFactoryTests extends BaseWebClientTests {
*/
}
@Test
public void shouldSetStatusIntAndAddOriginalHeader() {
String headerName = "original-http-status";
filterFactory.setOriginalStatusHeaderName(headerName);
setStatusStringTest("www.setstatusint.org", HttpStatus.UNAUTHORIZED)
.expectHeader().value(headerName, Matchers.is("[200]"));
}
@Test
public void toStringFormat() {
Config config = new Config();
@@ -86,6 +96,11 @@ public class SetStatusGatewayFilterFactoryTests extends BaseWebClientTests {
assertThat(filter.toString()).contains("401");
}
private WebTestClient.ResponseSpec setStatusStringTest(String host, HttpStatus status) {
return testClient.get().uri("/headers").header("Host", host).exchange()
.expectStatus().isEqualTo(status);
}
@EnableAutoConfiguration
@SpringBootConfiguration
@Import(DefaultTestConfig.class)
@@ -96,10 +111,14 @@ public class SetStatusGatewayFilterFactoryTests extends BaseWebClientTests {
@Bean
public RouteLocator myRouteLocator(RouteLocatorBuilder builder) {
// @formatter:off
return builder.routes()
.route("test_custom_http_status", r -> r.host("*.setcustomstatus.org")
.filters(f -> f.setStatus(432)).uri(uri))
.route("test_custom_http_status",
r -> r.host("*.setcustomstatus.org")
.filters(f -> f.setStatus(432))
.uri(uri))
.build();
// @formatter:on
}
}