Adds AddRequestParameter
This commit is contained in:
@@ -13,6 +13,7 @@ import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter;
|
||||
import org.springframework.cloud.gateway.filter.WriteResponseFilter;
|
||||
import org.springframework.cloud.gateway.filter.route.AddRequestHeaderRouteFilter;
|
||||
import org.springframework.cloud.gateway.filter.route.AddRequestParameterRouteFilter;
|
||||
import org.springframework.cloud.gateway.filter.route.AddResponseHeaderRouteFilter;
|
||||
import org.springframework.cloud.gateway.filter.route.RemoveRequestHeaderRouteFilter;
|
||||
import org.springframework.cloud.gateway.filter.route.RemoveResponseHeaderRouteFilter;
|
||||
@@ -130,6 +131,11 @@ public class GatewayAutoConfiguration {
|
||||
return new AddRequestHeaderRouteFilter();
|
||||
}
|
||||
|
||||
@Bean(name = "AddRequestParameterRouteFilter")
|
||||
public AddRequestParameterRouteFilter addRequestParameterRouteFilter() {
|
||||
return new AddRequestParameterRouteFilter();
|
||||
}
|
||||
|
||||
@Bean(name = "AddResponseHeaderRouteFilter")
|
||||
public AddResponseHeaderRouteFilter addResponseHeaderRouteFilter() {
|
||||
return new AddResponseHeaderRouteFilter();
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package org.springframework.cloud.gateway.filter.route;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class AddRequestParameterRouteFilter implements RouteFilter {
|
||||
|
||||
@Override
|
||||
public WebFilter apply(String parameter, String[] args) {
|
||||
validate(args, 1);
|
||||
|
||||
//TODO: caching can happen here
|
||||
return (exchange, chain) -> {
|
||||
|
||||
URI uri = exchange.getRequest().getURI();
|
||||
StringBuilder query = new StringBuilder();
|
||||
String originalQuery = uri.getQuery();
|
||||
|
||||
if (StringUtils.hasText(originalQuery)) {
|
||||
query.append(originalQuery);
|
||||
if (originalQuery.charAt(originalQuery.length() - 1) != '&') {
|
||||
query.append('&');
|
||||
}
|
||||
}
|
||||
|
||||
//TODO urlencode?
|
||||
query.append(parameter);
|
||||
query.append('=');
|
||||
query.append(args[0]);
|
||||
|
||||
ServerHttpRequest request = new QueryParamServerHttpRequestBuilder(exchange.getRequest())
|
||||
.query(query.toString())
|
||||
.build();
|
||||
|
||||
return chain.filter(exchange.mutate().request(request).build());
|
||||
};
|
||||
}
|
||||
|
||||
class QueryParamServerHttpRequestBuilder implements ServerHttpRequest.Builder {
|
||||
|
||||
private final ServerHttpRequest delegate;
|
||||
private String query;
|
||||
|
||||
public QueryParamServerHttpRequestBuilder(ServerHttpRequest delegate) {
|
||||
Assert.notNull(delegate, "ServerHttpRequest delegate is required");
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ServerHttpRequest.Builder method(HttpMethod httpMethod) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerHttpRequest.Builder path(String path) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ServerHttpRequest.Builder query(String query) {
|
||||
this.query = query;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerHttpRequest.Builder contextPath(String contextPath) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerHttpRequest.Builder header(String key, String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerHttpRequest build() {
|
||||
URI uri = null;
|
||||
if (this.query != null) {
|
||||
uri = this.delegate.getURI();
|
||||
try {
|
||||
uri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(),
|
||||
uri.getPath(), this.query, uri.getFragment());
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new IllegalStateException("Invalid URI query: \"" + this.query + "\"");
|
||||
}
|
||||
}
|
||||
return new MutativeDecorator(this.delegate, uri);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An immutable wrapper of a request returning property overrides -- given
|
||||
* to the constructor -- or original values otherwise.
|
||||
*/
|
||||
private class MutativeDecorator extends ServerHttpRequestDecorator {
|
||||
|
||||
private final URI uri;
|
||||
|
||||
public MutativeDecorator(ServerHttpRequest delegate, URI uri) {
|
||||
super(delegate);
|
||||
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpMethod getMethod() {
|
||||
return super.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getURI() {
|
||||
return (this.uri != null ? this.uri : super.getURI());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextPath() {
|
||||
return super.getContextPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return super.getHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ public class GatewayIntegrationTests {
|
||||
|
||||
private static final String HANDLER_MAPPER_HEADER = "X-Gateway-Handler-Mapper-Class";
|
||||
private static final String ROUTE_ID_HEADER = "X-Gateway-Route-Id";
|
||||
public static final Duration DURATION = Duration.ofSeconds(3);
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
@@ -100,7 +101,37 @@ public class GatewayIntegrationTests {
|
||||
assertThat(headers).containsEntry("X-Request-Foo", "Bar");
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addRequestParameterFilterWorksBlankQuery() {
|
||||
testRequestParameterFilter("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addRequestParameterFilterWorksNonBlankQuery() {
|
||||
testRequestParameterFilter("?baz=bam");
|
||||
}
|
||||
|
||||
private void testRequestParameterFilter(String query) {
|
||||
Mono<Map> result = webClient.exchange(
|
||||
GET("http://localhost:" + port + "/get" + query)
|
||||
.header("Host", "www.addrequestparameter.org")
|
||||
.build()
|
||||
).then(response -> response.body(toMono(Map.class)));
|
||||
|
||||
verify( () ->
|
||||
StepVerifier.create(result)
|
||||
.consumeNextWith(
|
||||
response -> {
|
||||
assertThat(response).containsKey("args").isInstanceOf(Map.class);
|
||||
Map<String, Object> args = (Map<String, Object>) response.get("args");
|
||||
assertThat(args).containsEntry("foo", "bar");
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -121,7 +152,7 @@ public class GatewayIntegrationTests {
|
||||
.isEqualTo("Bar");
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -175,7 +206,7 @@ public class GatewayIntegrationTests {
|
||||
assertThat(statusCode).isEqualTo(HttpStatus.OK);
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -192,7 +223,7 @@ public class GatewayIntegrationTests {
|
||||
StepVerifier.create(result)
|
||||
.consumeNextWith(map -> assertThat(map).containsEntry("data", "testdata"))
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -215,7 +246,7 @@ public class GatewayIntegrationTests {
|
||||
assertThat(headers).doesNotContainKey("X-Request-Foo");
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -235,7 +266,7 @@ public class GatewayIntegrationTests {
|
||||
assertThat(httpHeaders).doesNotContainKey("X-Request-Foo");
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -255,7 +286,7 @@ public class GatewayIntegrationTests {
|
||||
assertThat(statusCode).isEqualTo(HttpStatus.OK);
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -275,7 +306,7 @@ public class GatewayIntegrationTests {
|
||||
assertThat(statusCode).isEqualTo(HttpStatus.OK);
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -296,7 +327,7 @@ public class GatewayIntegrationTests {
|
||||
assertThat(httpHeaders.get("X-Request-Foo")).containsExactly("Bar");
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -325,7 +356,7 @@ public class GatewayIntegrationTests {
|
||||
assertThat(statusCode).isEqualTo(status);
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -348,7 +379,7 @@ public class GatewayIntegrationTests {
|
||||
assertThat(statusCode).isEqualTo(HttpStatus.OK);
|
||||
})
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(3))
|
||||
.verify(DURATION)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,15 @@ spring:
|
||||
filters:
|
||||
- AddRequestHeader=X-Request-Foo, Bar
|
||||
|
||||
# =====================================
|
||||
- id: add_request_parameter_test
|
||||
uri: http://httpbin.org:80
|
||||
predicates:
|
||||
- Host=**.addrequestparameter.org
|
||||
- Url=/get
|
||||
filters:
|
||||
- AddRequestParameter=foo, bar
|
||||
|
||||
# =====================================
|
||||
- id: add_response_header_test
|
||||
uri: http://httpbin.org:80
|
||||
|
||||
Reference in New Issue
Block a user