Updates to framework changes

This commit is contained in:
Spencer Gibb
2017-08-07 18:39:20 -06:00
parent e670f9c1cd
commit 9d5b8e6cfd
9 changed files with 69 additions and 30 deletions

View File

@@ -18,7 +18,6 @@
package org.springframework.cloud.gateway.filter;
import java.net.URI;
import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -55,19 +54,19 @@ public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
Optional<URI> url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
if (!url.isPresent() || !url.get().getScheme().equals("lb")) {
URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
if (url == null || !url.getScheme().equals("lb")) {
return chain.filter(exchange);
}
log.trace("LoadBalancerClientFilter url before: " + url.get());
log.trace("LoadBalancerClientFilter url before: " + url);
final ServiceInstance instance = loadBalancer.choose(url.get().getHost());
final ServiceInstance instance = loadBalancer.choose(url.getHost());
if (instance == null) {
throw new NotFoundException("");
}
URI requestUrl = UriComponentsBuilder.fromUri(url.get())
URI requestUrl = UriComponentsBuilder.fromUri(url)
.scheme(instance.isSecure()? "https" : "http") //TODO: support websockets
.host(instance.getHost())
.port(instance.getPort())

View File

@@ -20,7 +20,6 @@ package org.springframework.cloud.gateway.filter;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
@@ -61,19 +60,34 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
Optional<URI> requestUrl = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
if (!requestUrl.isPresent()) {
return Mono.error(new IllegalStateException("No URI found in attribute: " + GATEWAY_REQUEST_URL_ATTR));
}
URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);
ServerHttpRequest request = exchange.getRequest();
final HttpMethod method = HttpMethod.valueOf(request.getMethod().toString());
final String url = requestUrl.get().toString();
final String url = requestUrl.toString();
final DefaultHttpHeaders httpHeaders = new DefaultHttpHeaders();
request.getHeaders().forEach(httpHeaders::set);
if ("WebSocket".equalsIgnoreCase(request.getHeaders().getUpgrade())) {
return this.httpClient.ws(url)
// .flatMap(res -> {
.doOnNext(res -> {
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()));
response.getHeaders().putAll(headers);
response.setStatusCode(HttpStatus.valueOf(res.status().code()));
// Defer committing the response until all route filters have run
// Put client response as ServerWebExchange attribute and write response later WriteResponseFilter
exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);
}).then(chain.filter(exchange));
}
return this.httpClient.request(method, url, req -> {
final HttpClientRequest proxyRequest = req.options(NettyPipeline.SendOptions::flushOnEach)
.failOnClientError(false)
@@ -89,6 +103,8 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered {
}
}).then())
.then(chain.filter(exchange));
} else if ("WebSocket".equalsIgnoreCase(request.getHeaders().getUpgrade())) {
return proxyRequest.sendWebsocket();
}
return proxyRequest.sendHeaders() //I shouldn't need this

View File

@@ -18,7 +18,6 @@
package org.springframework.cloud.gateway.filter;
import java.net.URI;
import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -48,13 +47,13 @@ public class RouteToRequestUrlFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
Optional<Route> route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
if (!route.isPresent()) {
Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
if (route == null) {
return chain.filter(exchange);
}
log.info("RouteToRequestUrlFilter start");
URI requestUrl = UriComponentsBuilder.fromHttpRequest(exchange.getRequest())
.uri(route.get().getUri())
.uri(route.getUri())
.build(true)
.toUri();
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);

View File

@@ -53,9 +53,9 @@ public class WriteResponseFilter implements GlobalFilter, Ordered {
// NOTICE: nothing in "pre" filter stage as CLIENT_RESPONSE_ATTR is not added
// until the WebHandler is run
return chain.filter(exchange).then(Mono.defer(() -> {
Optional<HttpClientResponse> clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR);
HttpClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR);
// HttpClientResponse clientResponse = getAttribute(exchange, CLIENT_RESPONSE_ATTR, HttpClientResponse.class);
if (!clientResponse.isPresent()) {
if (clientResponse == null) {
return Mono.empty();
}
log.trace("WriteResponseFilter start");
@@ -64,7 +64,7 @@ public class WriteResponseFilter implements GlobalFilter, Ordered {
NettyDataBufferFactory factory = (NettyDataBufferFactory) response.bufferFactory();
//TODO: what if it's not netty
final Flux<NettyDataBuffer> body = clientResponse.get().receive()
final Flux<NettyDataBuffer> body = clientResponse.receive()
.retain() //TODO: needed?
.map(factory::wrap);

View File

@@ -22,12 +22,12 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.WebFilter;
import org.springframework.web.util.UriTemplate;
import org.springframework.web.util.pattern.PathPattern.PathMatchResult;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
@@ -38,6 +38,7 @@ public class SetPathWebFilterFactory implements WebFilterFactory {
public static final String TEMPLATE_KEY = "template";
@Override
public List<String> argNames() {
return Arrays.asList(TEMPLATE_KEY);
@@ -50,9 +51,17 @@ public class SetPathWebFilterFactory implements WebFilterFactory {
UriTemplate uriTemplate = new UriTemplate(template);
return (exchange, chain) -> {
Optional<Map<String, String>> variables = exchange.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
PathMatchResult variables = exchange.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
ServerHttpRequest req = exchange.getRequest();
URI uri = uriTemplate.expand(variables.orElseGet(Collections::emptyMap));
Map<String, String> uriVariables;
if (variables != null) {
uriVariables = variables.getUriVariables();
} else {
uriVariables = Collections.emptyMap();
}
URI uri = uriTemplate.expand(uriVariables);
String newPath = uri.getPath();
ServerHttpRequest request = req.mutate()

View File

@@ -81,8 +81,8 @@ public class FilteringWebHandler extends WebHandlerDecorator {
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
Optional<Route> route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
List<WebFilter> webFilters = route.get().getWebFilters();
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
List<WebFilter> webFilters = route.getWebFilters();
List<WebFilter> combined = new ArrayList<>(this.globalFilters);
combined.addAll(webFilters);

View File

@@ -19,16 +19,18 @@ package org.springframework.cloud.gateway.handler.predicate;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import org.springframework.http.server.reactive.PathContainer;
import org.springframework.tuple.Tuple;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPattern.PathMatchResult;
import org.springframework.web.util.pattern.PathPatternParser;
import static org.springframework.cloud.gateway.handler.support.RoutePredicateFactoryUtils.traceMatch;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
import static org.springframework.http.server.reactive.PathContainer.parsePath;
/**
* @author Spencer Gibb
@@ -55,11 +57,12 @@ public class PathRoutePredicateFactory implements RoutePredicateFactory {
}
return exchange -> {
String path = exchange.getRequest().getURI().getPath();
PathContainer path = parsePath(exchange.getRequest().getURI().getPath());
boolean match = pattern.matches(path);
traceMatch("Pattern", pattern.getPatternString(), path, match);
if (match) {
Map<String, String> uriTemplateVariables = pattern.matchAndExtract(path);
PathMatchResult uriTemplateVariables = pattern.matchAndExtract(path);
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
return true;
}

View File

@@ -17,16 +17,21 @@
package org.springframework.cloud.gateway.filter.factory;
import java.lang.reflect.Constructor;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.MockServerWebExchange;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.util.pattern.PathPattern;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -62,7 +67,15 @@ public class SetPathWebFilterFactoryTests {
.build();
ServerWebExchange exchange = new MockServerWebExchange(request);
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, variables);
try {
Constructor<PathPattern.PathMatchResult> constructor = ReflectionUtils.accessibleConstructor(PathPattern.PathMatchResult.class, Map.class, Map.class);
constructor.setAccessible(true);
PathPattern.PathMatchResult pathMatchResult = constructor.newInstance(variables, Collections.emptyMap());
exchange.getAttributes().put(URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathMatchResult);
} catch (Exception e) {
ReflectionUtils.rethrowRuntimeException(e);
}
WebFilterChain filterChain = mock(WebFilterChain.class);

View File

@@ -174,9 +174,9 @@ public class BaseWebClientTests {
public GlobalFilter modifyResponseFilter() {
return (exchange, chain) -> {
log.info("modifyResponseFilter start");
String value = (String) exchange.getAttribute(GATEWAY_HANDLER_MAPPER_ATTR).orElse("N/A");
String value = exchange.getAttributeOrDefault(GATEWAY_HANDLER_MAPPER_ATTR, "N/A");
exchange.getResponse().getHeaders().add(HANDLER_MAPPER_HEADER, value);
Route route = (Route) exchange.getAttribute(GATEWAY_ROUTE_ATTR).orElse(null);
Route route = exchange.getAttributeOrDefault(GATEWAY_ROUTE_ATTR,null);
if (route != null) {
exchange.getResponse().getHeaders().add(ROUTE_ID_HEADER, route.getId());
}