Move from WebFilter to GatewayFilter.
Add GatewayHostHandlerMapping
This commit is contained in:
@@ -20,10 +20,9 @@ public class GatewayApplication {
|
||||
|
||||
private static final Log log = LogFactory.getLog(GatewayApplication.class);
|
||||
|
||||
// TODO: only apply filters to zuul?
|
||||
@Bean
|
||||
@Order(501)
|
||||
public WebFilter modifyResponseFilter() {
|
||||
public GatewayFilter modifyResponseFilter() {
|
||||
return (exchange, chain) -> {
|
||||
log.info("modifyResponseFilter start");
|
||||
exchange.getResponse().getHeaders().add("X-My-Custom", "MyCustomValue");
|
||||
@@ -33,7 +32,7 @@ public class GatewayApplication {
|
||||
|
||||
@Bean
|
||||
@Order(502)
|
||||
public WebFilter postFilter() {
|
||||
public GatewayFilter postFilter() {
|
||||
return (exchange, chain) -> {
|
||||
log.info("postFilter start");
|
||||
return chain.filter(exchange).then(postFilterWork(exchange));
|
||||
@@ -49,7 +48,6 @@ public class GatewayApplication {
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder()
|
||||
.sources(GatewayApplication.class)
|
||||
//TODO: howto do programatically
|
||||
.run(args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.springframework.cloud.gateway;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.gateway.filters.FindRouteFilter;
|
||||
import org.springframework.cloud.gateway.filters.RouteToUrlFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
@@ -22,8 +22,8 @@ public class GatewayConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FindRouteFilter findRouteFilter(GatewayProperties properties) {
|
||||
return new FindRouteFilter(properties);
|
||||
public RouteToUrlFilter findRouteFilter(GatewayProperties properties) {
|
||||
return new RouteToUrlFilter(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -37,18 +37,18 @@ public class GatewayConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GatewayHandlerMapping gatewayHandlerMapping(GatewayProperties properties, GatewayWebHandler gatewayWebHandler) {
|
||||
return new GatewayHandlerMapping(properties, gatewayWebHandler);
|
||||
public GatewayFilteringWebHandler gatewayFilteringWebHandler(GatewayWebHandler gatewayWebHandler, GatewayFilter[] filters) {
|
||||
return new GatewayFilteringWebHandler(gatewayWebHandler, filters);
|
||||
}
|
||||
|
||||
/*@Bean
|
||||
public GatewayWebReactiveConfigurer gatewayWebReactiveConfiguration() {
|
||||
return new GatewayWebReactiveConfigurer();
|
||||
@Bean
|
||||
public GatewayUrlHandlerMapping gatewayUrlHandlerMapping(GatewayProperties properties, GatewayFilteringWebHandler webHandler) {
|
||||
return new GatewayUrlHandlerMapping(properties, webHandler);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GatewayHostHandlerMapping gatewayHostHandlerMapping(GatewayProperties properties, GatewayFilteringWebHandler webHandler) {
|
||||
return new GatewayHostHandlerMapping(properties, webHandler);
|
||||
}
|
||||
|
||||
public static class GatewayWebReactiveConfigurer implements WebReactiveConfigurer {
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.gateway;
|
||||
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Contract for interception-style, chained processing of Web requests that may
|
||||
* be used to implement cross-cutting, application-agnostic requirements such
|
||||
* as security, timeouts, and others.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface GatewayFilter {
|
||||
|
||||
default boolean shouldFilter(ServerWebExchange exchange) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the Web request and (optionally) delegate to the next
|
||||
* {@code WebFilter} through the given {@link WebFilterChain}.
|
||||
* @param exchange the current server exchange
|
||||
* @param chain provides a way to delegate to the next filter
|
||||
* @return {@code Mono<Void>} to indicate when request processing is complete
|
||||
*/
|
||||
Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.gateway;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.handler.WebHandlerDecorator;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* WebHandler that delegates to a chain of {@link GatewayFilter} instances and then
|
||||
* to the target {@link WebHandler}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class GatewayFilteringWebHandler extends WebHandlerDecorator {
|
||||
|
||||
private final List<GatewayFilter> filters;
|
||||
|
||||
|
||||
public GatewayFilteringWebHandler(WebHandler targetHandler, GatewayFilter... filters) {
|
||||
super(targetHandler);
|
||||
this.filters = initList(filters);
|
||||
}
|
||||
|
||||
private static List<GatewayFilter> initList(GatewayFilter[] list) {
|
||||
return (list != null ? Collections.unmodifiableList(Arrays.asList(list)) : Collections.emptyList());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a read-only list of the configured filters.
|
||||
*/
|
||||
public List<GatewayFilter> getFilters() {
|
||||
return this.filters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange) {
|
||||
return new DefaultWebFilterChain().filter(exchange);
|
||||
}
|
||||
|
||||
|
||||
private class DefaultWebFilterChain implements WebFilterChain {
|
||||
|
||||
private int index;
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange) {
|
||||
if (this.index < filters.size()) {
|
||||
GatewayFilter filter = filters.get(this.index++);
|
||||
if (filter.shouldFilter(exchange)) {
|
||||
return filter.filter(exchange, this);
|
||||
} else {
|
||||
return this.filter(exchange);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return getDelegate().handle(exchange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.springframework.cloud.gateway;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cloud.gateway.GatewayProperties.Route;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class GatewayHandlerMapping extends AbstractUrlHandlerMapping {
|
||||
|
||||
private GatewayProperties properties;
|
||||
private GatewayWebHandler gatewayWebHandler;
|
||||
|
||||
public GatewayHandlerMapping(GatewayProperties properties, GatewayWebHandler gatewayWebHandler) {
|
||||
this.properties = properties;
|
||||
this.gatewayWebHandler = gatewayWebHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initApplicationContext() throws BeansException {
|
||||
super.initApplicationContext();
|
||||
registerHandlers(this.properties.getRoutes());
|
||||
}
|
||||
|
||||
protected void registerHandlers(Map<String, Route> routes) {
|
||||
for (Route route : routes.values()) {
|
||||
if (StringUtils.hasText(route.getRequestPath())) {
|
||||
registerHandler(route.getRequestPath(), this.gatewayWebHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
package org.springframework.cloud.gateway;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cloud.gateway.GatewayProperties.Route;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.reactive.handler.AbstractHandlerMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class GatewayHostHandlerMapping extends AbstractHandlerMapping {
|
||||
|
||||
private GatewayProperties properties;
|
||||
private WebHandler webHandler;
|
||||
|
||||
private final Map<String, Object> handlerMap = new LinkedHashMap<>();
|
||||
|
||||
public GatewayHostHandlerMapping(GatewayProperties properties, WebHandler webHandler) {
|
||||
this.properties = properties;
|
||||
this.webHandler = webHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initApplicationContext() throws BeansException {
|
||||
super.initApplicationContext();
|
||||
registerHandlers(this.properties.getRoutes());
|
||||
setPathMatcher(new AntPathMatcher("."));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
|
||||
String host = exchange.getRequest().getHeaders().getFirst("Host");
|
||||
Object handler;
|
||||
try {
|
||||
handler = lookupHandler(host, exchange);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return Mono.error(ex);
|
||||
}
|
||||
|
||||
if (handler != null && logger.isDebugEnabled()) {
|
||||
logger.debug("Mapping [" + host + "] to " + handler);
|
||||
}
|
||||
else if (handler == null && logger.isTraceEnabled()) {
|
||||
logger.trace("No handler mapping found for [" + host + "]");
|
||||
}
|
||||
|
||||
return Mono.justOrEmpty(handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look up a handler instance for the given URL path.
|
||||
*
|
||||
* <p>Supports direct matches, e.g. a registered "/test" matches "/test",
|
||||
* and various Ant-style pattern matches, e.g. a registered "/t*" matches
|
||||
* both "/test" and "/team". For details, see the AntPathMatcher class.
|
||||
*
|
||||
* <p>Looks for the most exact pattern, where most exact is defined as
|
||||
* the longest path pattern.
|
||||
*
|
||||
* @param host URL the bean is mapped to
|
||||
* @param exchange the current exchange
|
||||
* @return the associated handler instance, or {@code null} if not found
|
||||
* @see org.springframework.util.AntPathMatcher
|
||||
*/
|
||||
protected Object lookupHandler(String host, ServerWebExchange exchange) throws Exception {
|
||||
// Direct match?
|
||||
Object handler = this.handlerMap.get(host);
|
||||
if (handler != null) {
|
||||
return handleMatch(handler, host, exchange);
|
||||
}
|
||||
// Pattern match?
|
||||
List<String> matches = new ArrayList<>();
|
||||
for (String pattern : this.handlerMap.keySet()) {
|
||||
if (getPathMatcher().match(pattern, host)) {
|
||||
matches.add(pattern);
|
||||
}
|
||||
}
|
||||
String bestMatch = null;
|
||||
Comparator<String> comparator = getPathMatcher().getPatternComparator(host);
|
||||
if (!matches.isEmpty()) {
|
||||
Collections.sort(matches, comparator);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Matching patterns for request [" + host + "] are " + matches);
|
||||
}
|
||||
bestMatch = matches.get(0);
|
||||
}
|
||||
if (bestMatch != null) {
|
||||
handler = this.handlerMap.get(bestMatch);
|
||||
if (handler == null) {
|
||||
Assert.isTrue(bestMatch.endsWith("/"));
|
||||
handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
|
||||
}
|
||||
return handleMatch(handler, bestMatch, exchange);
|
||||
}
|
||||
// No handler found...
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private Object handleMatch(Object handler, String bestMatch,
|
||||
ServerWebExchange exchange) throws Exception {
|
||||
|
||||
// Bean name or resolved handler?
|
||||
if (handler instanceof String) {
|
||||
String handlerName = (String) handler;
|
||||
handler = getApplicationContext().getBean(handlerName);
|
||||
}
|
||||
|
||||
if (handler instanceof RouteHolder) {
|
||||
RouteHolder holder = (RouteHolder) handler;
|
||||
exchange.getAttributes().put("gatewayRoute", holder.route);
|
||||
return holder.webHandler;
|
||||
}
|
||||
|
||||
validateHandler(handler, exchange);
|
||||
|
||||
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestMatch);
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the given handler against the current request.
|
||||
* <p>The default implementation is empty. Can be overridden in subclasses,
|
||||
* for example to enforce specific preconditions expressed in URL mappings.
|
||||
* @param handler the handler object to validate
|
||||
* @param exchange current exchange
|
||||
* @throws Exception if validation failed
|
||||
*/
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
protected void validateHandler(Object handler, ServerWebExchange exchange) throws Exception {
|
||||
}
|
||||
|
||||
|
||||
protected void registerHandlers(Map<String, Route> routes) {
|
||||
for (Route route : routes.values()) {
|
||||
if (StringUtils.hasText(route.getRequestHost())) {
|
||||
registerHandler(route.getRequestHost(), new RouteHolder(route, this.webHandler));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the specified handler for the given host path.
|
||||
* @param hostPath the host the bean should be mapped to
|
||||
* @param handler the handler instance or handler bean name String
|
||||
* (a bean name will automatically be resolved into the corresponding handler bean)
|
||||
* @throws BeansException if the handler couldn't be registered
|
||||
* @throws IllegalStateException if there is a conflicting handler registered
|
||||
*/
|
||||
protected void registerHandler(String hostPath, Object handler) throws BeansException, IllegalStateException {
|
||||
Assert.notNull(hostPath, "host path must not be null");
|
||||
Assert.notNull(handler, "Handler object must not be null");
|
||||
Object resolvedHandler = handler;
|
||||
|
||||
// Eagerly resolve handler if referencing singleton via name.
|
||||
/*if (!this.lazyInitHandlers && handler instanceof String) {
|
||||
String handlerName = (String) handler;
|
||||
if (getApplicationContext().isSingleton(handlerName)) {
|
||||
resolvedHandler = getApplicationContext().getBean(handlerName);
|
||||
}
|
||||
}*/
|
||||
|
||||
Object mappedHandler = this.handlerMap.get(hostPath);
|
||||
if (mappedHandler != null) {
|
||||
if (mappedHandler != resolvedHandler) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot map " + getHandlerDescription(handler) + " to host path [" + hostPath +
|
||||
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.handlerMap.put(hostPath, resolvedHandler);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Mapped host path [" + hostPath + "] onto " + getHandlerDescription(handler));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String getHandlerDescription(Object handler) {
|
||||
String desc;
|
||||
if (handler instanceof String) {
|
||||
desc = "'" + handler + "'";
|
||||
} else if (handler instanceof RouteHolder) {
|
||||
desc = "of type [" + ((RouteHolder) handler).webHandler.getClass() + "]";
|
||||
} else {
|
||||
desc = "of type [" + handler.getClass() + "]";
|
||||
}
|
||||
return "handler " + desc;
|
||||
}
|
||||
|
||||
private class RouteHolder {
|
||||
private final Route route;
|
||||
private final WebHandler webHandler;
|
||||
|
||||
public RouteHolder(Route route, WebHandler webHandler) {
|
||||
this.route = route;
|
||||
this.webHandler = webHandler;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.springframework.cloud.gateway;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cloud.gateway.GatewayProperties.Route;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.reactive.handler.AbstractUrlHandlerMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class GatewayUrlHandlerMapping extends AbstractUrlHandlerMapping {
|
||||
|
||||
private GatewayProperties properties;
|
||||
private WebHandler webHandler;
|
||||
|
||||
public GatewayUrlHandlerMapping(GatewayProperties properties, WebHandler webHandler) {
|
||||
this.properties = properties;
|
||||
this.webHandler = webHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initApplicationContext() throws BeansException {
|
||||
super.initApplicationContext();
|
||||
registerHandlers(this.properties.getRoutes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> getHandler(ServerWebExchange exchange) {
|
||||
return super.getHandler(exchange).map(o -> {
|
||||
if (o instanceof RouteHolder) {
|
||||
RouteHolder holder = (RouteHolder) o;
|
||||
exchange.getAttributes().put("gatewayRoute", holder.route);
|
||||
return holder.webHandler;
|
||||
}
|
||||
return o;
|
||||
});
|
||||
}
|
||||
|
||||
protected void registerHandlers(Map<String, Route> routes) {
|
||||
for (Route route : routes.values()) {
|
||||
if (StringUtils.hasText(route.getRequestPath())) {
|
||||
registerHandler(route.getRequestPath(), new RouteHolder(route, this.webHandler));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class RouteHolder {
|
||||
private final Route route;
|
||||
private final WebHandler webHandler;
|
||||
|
||||
public RouteHolder(Route route, WebHandler webHandler) {
|
||||
this.route = route;
|
||||
this.webHandler = webHandler;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,6 +28,7 @@ public class GatewayWebHandler implements WebHandler {
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange) {
|
||||
//TODO: move to constant
|
||||
Optional<URI> requestUrl = exchange.getAttribute("requestUrl");
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
ClientRequest<Void> clientRequest = ClientRequest
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
package org.springframework.cloud.gateway.filters;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.gateway.GatewayProperties;
|
||||
import org.springframework.cloud.gateway.GatewayProperties.Route;
|
||||
import org.springframework.cloud.gateway.GatewayApplication;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class FindRouteFilter implements WebFilter, Ordered {
|
||||
|
||||
private static final Log log = LogFactory.getLog(GatewayApplication.class);
|
||||
|
||||
private final GatewayProperties properties;
|
||||
private final AntPathMatcher pathMatcher = new AntPathMatcher();
|
||||
private final AntPathMatcher hostMatcher = new AntPathMatcher(".");
|
||||
|
||||
public FindRouteFilter(GatewayProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 500;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
log.info("FindRouteFilter start");
|
||||
//TODO:
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
URI uri = request.getURI();
|
||||
String path = uri.getPath();
|
||||
String host = uri.getHost();
|
||||
for (Route route : this.properties.getRoutes().values()) {
|
||||
if (hasText(route.getRequestPath())
|
||||
&& this.pathMatcher.match(route.getRequestPath(), path)) {
|
||||
populateRequestUrl(exchange, request, route);
|
||||
// TODO: this stuff needs to move into GatewayHandlerMapping
|
||||
// otherwise, only path based routing works
|
||||
} else if (hasText(route.getRequestHost())
|
||||
&& this.hostMatcher.match(route.getRequestHost(), host)) {
|
||||
populateRequestUrl(exchange, request, route);
|
||||
}
|
||||
}
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
private void populateRequestUrl(ServerWebExchange exchange, ServerHttpRequest request, Route route) {
|
||||
URI requestUrl = UriComponentsBuilder.fromHttpRequest(request)
|
||||
.uri(route.getDownstreamUrl())
|
||||
.build(true)
|
||||
.toUri();
|
||||
exchange.getAttributes().put("requestUrl", requestUrl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.springframework.cloud.gateway.filters;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.gateway.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.GatewayProperties;
|
||||
import org.springframework.cloud.gateway.GatewayProperties.Route;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class RouteToUrlFilter implements GatewayFilter, Ordered {
|
||||
|
||||
private static final Log log = LogFactory.getLog(RouteToUrlFilter.class);
|
||||
|
||||
private final GatewayProperties properties;
|
||||
|
||||
public RouteToUrlFilter(GatewayProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
// TODO: move to constant
|
||||
return 500;
|
||||
}
|
||||
|
||||
// TODO: do we really need shouldFilter or just move the if into filter?
|
||||
@Override
|
||||
public boolean shouldFilter(ServerWebExchange exchange) {
|
||||
//TODO: move to constant
|
||||
return exchange.getAttributes().containsKey("gatewayRoute");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||
log.info("RouteToUrlFilter start");
|
||||
Object gatewayRoute = exchange.getAttributes().get("gatewayRoute");
|
||||
if (!(gatewayRoute instanceof Route)) {
|
||||
return Mono.error(new IllegalStateException("gatewayRoute" +
|
||||
" not an instance of " + Route.class.getSimpleName() +
|
||||
", is " + gatewayRoute.getClass()));
|
||||
}
|
||||
Route route = (Route) gatewayRoute;
|
||||
URI requestUrl = UriComponentsBuilder.fromHttpRequest(exchange.getRequest())
|
||||
.uri(route.getDownstreamUrl())
|
||||
.build(true)
|
||||
.toUri();
|
||||
//TODO: move to constant
|
||||
exchange.getAttributes().put("requestUrl", requestUrl);
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
spring:
|
||||
resources:
|
||||
# TODO: how to add this programmatically
|
||||
@@ -5,7 +6,12 @@ spring:
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
test1:
|
||||
requestPath: /**
|
||||
# requestHost: '**.example.org'
|
||||
# test1:
|
||||
# requestPath: /**
|
||||
# downstreamUrl: http://httpbin.org:80
|
||||
test2:
|
||||
requestHost: '**.example.org'
|
||||
downstreamUrl: http://httpbin.org:80
|
||||
logging:
|
||||
level:
|
||||
org.springframework.cloud.gateway: TRACE
|
||||
|
||||
Reference in New Issue
Block a user