Add SetStatus filter

though it's broken because it sets the status after the response is commited.
This commit is contained in:
Spencer Gibb
2017-01-13 23:23:22 -07:00
parent 916ece75b8
commit 7843c7252e
4 changed files with 196 additions and 102 deletions

View File

@@ -17,6 +17,7 @@ import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderFilte
import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderFilterFactory;
import org.springframework.cloud.gateway.filter.factory.RewritePathFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SetStatusFilterFactory;
import org.springframework.cloud.gateway.handler.GatewayFilteringWebHandler;
import org.springframework.cloud.gateway.handler.GatewayPredicateHandlerMapping;
import org.springframework.cloud.gateway.handler.GatewayWebHandler;
@@ -144,6 +145,11 @@ public class GatewayAutoConfiguration {
return new SetResponseHeaderFilterFactory();
}
@Bean
public SetStatusFilterFactory setStatusFilterFactory() {
return new SetStatusFilterFactory();
}
@Configuration
@ConditionalOnClass(Endpoint.class)
protected static class GatewayActuatorConfiguration {

View File

@@ -0,0 +1,37 @@
package org.springframework.cloud.gateway.filter.factory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @author Spencer Gibb
*/
public class SetStatusFilterFactory implements FilterFactory {
@Override
public GatewayFilter apply(String statusString, String[] args) {
HttpStatus httpStatus;
try {
int status = Integer.parseInt(statusString);
httpStatus = HttpStatus.valueOf(status);
} catch (NumberFormatException e) {
// try the enum string
httpStatus = HttpStatus.valueOf(statusString.toUpperCase());
}
final HttpStatus finalStatus = httpStatus;
//TODO: caching can happen here
return (exchange, chain) ->
chain.filter(exchange).then(() -> setStatus(exchange, finalStatus));
}
protected Mono<Void> setStatus(ServerWebExchange exchange, HttpStatus status) {
exchange.getResponse().setStatusCode(status);
return Mono.empty();
}
}

View File

@@ -7,6 +7,7 @@ import java.util.stream.IntStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.SpringBootConfiguration;
@@ -81,74 +82,6 @@ public class GatewayIntegrationTests {
}
}
@Test
public void urlRouteWorks() {
Mono<ClientResponse> result = webClient.exchange(
GET("http://localhost:" + port + "/get").build()
);
verify( () ->
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpHeaders httpHeaders = response.headers().asHttpHeaders();
HttpStatus statusCode = response.statusCode();
assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER))
.isEqualTo(GatewayPredicateHandlerMapping.class.getSimpleName());
assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER))
.isEqualTo("default_path_to_httpbin");
assertThat(statusCode).isEqualTo(HttpStatus.OK);
})
.expectComplete()
.verify(Duration.ofSeconds(3))
);
}
@Test
public void hostRouteWorks() {
Mono<ClientResponse> result = webClient.exchange(
GET("http://localhost:" + port + "/get")
.header("Host", "www.example.org")
.build()
);
verify( () ->
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpHeaders httpHeaders = response.headers().asHttpHeaders();
HttpStatus statusCode = response.statusCode();
assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER))
.isEqualTo(GatewayPredicateHandlerMapping.class.getSimpleName());
assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER))
.isEqualTo("host_example_to_httpbin");
assertThat(statusCode).isEqualTo(HttpStatus.OK);
})
.expectComplete()
.verify(Duration.ofSeconds(3))
);
}
@Test
public void rewritePathFilterWorks() {
Mono<ClientResponse> result = webClient.exchange(
GET("http://localhost:" + port + "/foo/get")
.header("Host", "www.baz.org")
.build()
);
verify( () ->
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpStatus statusCode = response.statusCode();
assertThat(statusCode).isEqualTo(HttpStatus.OK);
})
.expectComplete()
.verify(Duration.ofSeconds(3))
);
}
@Test
public void addRequestHeaderFilterWorks() {
Mono<Map> result = webClient.exchange(
@@ -191,6 +124,77 @@ public class GatewayIntegrationTests {
);
}
@Test
public void compositeRouteWorks() {
Mono<ClientResponse> result = webClient.exchange(
GET("http://localhost:" + port + "/headers?foo=bar&baz")
.header("Host", "www.foo.org")
.header("X-Request-Id", "123")
.cookie("chocolate", "chip")
.build()
);
verify( () ->
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpHeaders httpHeaders = response.headers().asHttpHeaders();
HttpStatus statusCode = response.statusCode();
assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER))
.isEqualTo(GatewayPredicateHandlerMapping.class.getSimpleName());
assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER))
.isEqualTo("host_foo_path_headers_to_httpbin");
assertThat(httpHeaders.getFirst("X-Response-Foo"))
.isEqualTo("Bar");
assertThat(statusCode).isEqualTo(HttpStatus.OK);
})
.expectComplete()
.verify()
);
}
@Test
public void hostRouteWorks() {
Mono<ClientResponse> result = webClient.exchange(
GET("http://localhost:" + port + "/get")
.header("Host", "www.example.org")
.build()
);
verify( () ->
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpHeaders httpHeaders = response.headers().asHttpHeaders();
HttpStatus statusCode = response.statusCode();
assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER))
.isEqualTo(GatewayPredicateHandlerMapping.class.getSimpleName());
assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER))
.isEqualTo("host_example_to_httpbin");
assertThat(statusCode).isEqualTo(HttpStatus.OK);
})
.expectComplete()
.verify(Duration.ofSeconds(3))
);
}
@Test
public void postWorks() {
ClientRequest<Mono<String>> request = POST("http://localhost:" + port + "/post")
.header("Host", "www.example.org")
.body(Mono.just("testdata"), String.class);
Mono<Map> result = webClient.exchange(request)
.then(response -> response.body(toMono(Map.class)));
verify( () ->
StepVerifier.create(result)
.consumeNextWith(map -> assertThat(map).containsEntry("data", "testdata"))
.expectComplete()
.verify(Duration.ofSeconds(3))
);
}
@Test
@SuppressWarnings("unchecked")
public void removeRequestHeaderFilterWorks() {
@@ -234,6 +238,26 @@ public class GatewayIntegrationTests {
);
}
@Test
public void rewritePathFilterWorks() {
Mono<ClientResponse> result = webClient.exchange(
GET("http://localhost:" + port + "/foo/get")
.header("Host", "www.baz.org")
.build()
);
verify( () ->
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpStatus statusCode = response.statusCode();
assertThat(statusCode).isEqualTo(HttpStatus.OK);
})
.expectComplete()
.verify(Duration.ofSeconds(3))
);
}
@Test
public void setResponseHeaderFilterWorks() {
Mono<ClientResponse> result = webClient.exchange(
@@ -256,48 +280,56 @@ public class GatewayIntegrationTests {
}
@Test
public void postWorks() {
ClientRequest<Mono<String>> request = POST("http://localhost:" + port + "/post")
.header("Host", "www.example.org")
.body(Mono.just("testdata"), String.class);
Mono<Map> result = webClient.exchange(request)
.then(response -> response.body(toMono(Map.class)));
verify( () ->
StepVerifier.create(result)
.consumeNextWith(map -> assertThat(map).containsEntry("data", "testdata"))
.expectComplete()
.verify(Duration.ofSeconds(3))
);
@Ignore("TODO: figure out how to set the status before response committed")
public void setStatusStringWorks() {
setStatusStringTest("www.setstatusstring.org", HttpStatus.BAD_REQUEST);
}
@Test
public void compositeRouteWorks() {
@Ignore("TODO: figure out how to set the status before response committed")
public void setStatusIntWorks() {
setStatusStringTest("www.setstatusint.org", HttpStatus.UNAUTHORIZED);
}
private void setStatusStringTest(String host, HttpStatus status) {
Mono<ClientResponse> result = webClient.exchange(
GET("http://localhost:" + port + "/headers?foo=bar&baz")
.header("Host", "www.foo.org")
.header("X-Request-Id", "123")
.cookie("chocolate", "chip")
GET("http://localhost:" + port + "/headers")
.header("Host", host)
.build()
);
verify( () ->
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpHeaders httpHeaders = response.headers().asHttpHeaders();
HttpStatus statusCode = response.statusCode();
assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER))
.isEqualTo(GatewayPredicateHandlerMapping.class.getSimpleName());
assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER))
.isEqualTo("host_foo_path_headers_to_httpbin");
assertThat(httpHeaders.getFirst("X-Response-Foo"))
.isEqualTo("Bar");
assertThat(statusCode).isEqualTo(HttpStatus.OK);
})
.expectComplete()
.verify()
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpStatus statusCode = response.statusCode();
assertThat(statusCode).isEqualTo(status);
})
.expectComplete()
.verify(Duration.ofSeconds(3))
);
}
@Test
public void urlRouteWorks() {
Mono<ClientResponse> result = webClient.exchange(
GET("http://localhost:" + port + "/get").build()
);
verify( () ->
StepVerifier.create(result)
.consumeNextWith(
response -> {
HttpHeaders httpHeaders = response.headers().asHttpHeaders();
HttpStatus statusCode = response.statusCode();
assertThat(httpHeaders.getFirst(HANDLER_MAPPER_HEADER))
.isEqualTo(GatewayPredicateHandlerMapping.class.getSimpleName());
assertThat(httpHeaders.getFirst(ROUTE_ID_HEADER))
.isEqualTo("default_path_to_httpbin");
assertThat(statusCode).isEqualTo(HttpStatus.OK);
})
.expectComplete()
.verify(Duration.ofSeconds(3))
);
}

View File

@@ -68,6 +68,24 @@ spring:
- AddResponseHeader=X-Request-Foo, Bar2
- SetResponseHeader=X-Request-Foo, Bar
# =====================================
- id: set_status_string_test
uri: http://httpbin.org:80
predicates:
- Host=**.setstatusstring.org
- Url=/headers
filters:
- SetStatus=BAD_REQUEST
# =====================================
- id: set_status_int_test
uri: http://httpbin.org:80
predicates:
- Host=**.setstatusint.org
- Url=/headers
filters:
- SetStatus=401
# =====================================
- id: rewrite_path_test
uri: http://httpbin.org:80
@@ -88,6 +106,7 @@ spring:
logging:
level:
org.springframework.cloud.gateway: TRACE
org.springframework.http.server.reactive: DEBUG
management:
context-path: /admin