diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java index 2882917d..38c3dbc2 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/NettyRoutingFilter.java @@ -33,6 +33,8 @@ import org.springframework.web.server.WebFilterChain; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.isAlreadyRouted; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setAlreadyRouted; import io.netty.buffer.Unpooled; import io.netty.handler.codec.http.DefaultHttpHeaders; @@ -47,8 +49,6 @@ import reactor.ipc.netty.http.client.HttpClientRequest; */ public class NettyRoutingFilter implements GlobalFilter, Ordered { - //TODO: investigate using WebClient - //The WebSocketRoutingFilter worked out so well without a hard dependency on netty private final HttpClient httpClient; public NettyRoutingFilter(HttpClient httpClient) { @@ -65,9 +65,10 @@ public class NettyRoutingFilter implements GlobalFilter, Ordered { URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR); String scheme = requestUrl.getScheme(); - if (!scheme.equals("http") && !scheme.equals("https")) { + if (isAlreadyRouted(exchange) || (!scheme.equals("http") && !scheme.equals("https"))) { return chain.filter(exchange); } + setAlreadyRouted(exchange); ServerHttpRequest request = exchange.getRequest(); diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WebClientHttpRoutingFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WebClientHttpRoutingFilter.java index 287e38ea..fd275231 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WebClientHttpRoutingFilter.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WebClientHttpRoutingFilter.java @@ -33,6 +33,8 @@ import org.springframework.web.server.WebFilterChain; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.isAlreadyRouted; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setAlreadyRouted; import reactor.core.publisher.Mono; @@ -57,9 +59,10 @@ public class WebClientHttpRoutingFilter implements GlobalFilter, Ordered { URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR); String scheme = requestUrl.getScheme(); - if (!scheme.equals("http") && !scheme.equals("https")) { + if (isAlreadyRouted(exchange) || (!scheme.equals("http") && !scheme.equals("https"))) { return chain.filter(exchange); } + setAlreadyRouted(exchange); ServerHttpRequest request = exchange.getRequest(); diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WebsocketRoutingFilter.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WebsocketRoutingFilter.java index 35a00e15..a3266e9f 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WebsocketRoutingFilter.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/filter/WebsocketRoutingFilter.java @@ -17,6 +17,8 @@ import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilterChain; import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.isAlreadyRouted; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.setAlreadyRouted; import reactor.core.publisher.Mono; @@ -49,10 +51,10 @@ public class WebsocketRoutingFilter implements GlobalFilter, Ordered { URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR); String scheme = requestUrl.getScheme(); - if (!scheme.equals("ws") && !scheme.equals("wss")) { + if (isAlreadyRouted(exchange) || (!scheme.equals("ws") && !scheme.equals("wss"))) { return chain.filter(exchange); } - + setAlreadyRouted(exchange); return this.webSocketService.handleRequest(exchange, new ProxyWebSocketHandler(requestUrl, this.webSocketClient, exchange.getRequest().getHeaders())); @@ -84,6 +86,7 @@ public class WebsocketRoutingFilter implements GlobalFilter, Ordered { @Override public Mono handle(WebSocketSession session) { + // pass headers along so custom headers can be sent through return client.execute(url, this.headers, new WebSocketHandler() { @Override public Mono handle(WebSocketSession proxySession) { @@ -97,6 +100,10 @@ public class WebsocketRoutingFilter implements GlobalFilter, Ordered { return Mono.when(proxySessionSend, serverSessionSend).then(); } + /** + * Copy subProtocols so they are available downstream. + * @return + */ @Override public List getSubProtocols() { return ProxyWebSocketHandler.this.subProtocols; diff --git a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java index ec279f2f..d1d8cdb3 100644 --- a/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java +++ b/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java @@ -40,10 +40,24 @@ public class ServerWebExchangeUtils { public static final String GATEWAY_ORIGINAL_REQUEST_URL_ATTR = qualify("gatewayOribinalRequestUrl"); public static final String GATEWAY_HANDLER_MAPPER_ATTR = qualify("gatewayHandlerMapper"); + /** + * Used when a routing filter has been successfully call. Allows users to write custom + * routing filters that disable built in routing filters. + */ + public static final String GATEWAY_ALREADY_ROUTED_ATTR = qualify("gatewayAlreadyRouted"); + private static String qualify(String attr) { return ServerWebExchangeUtils.class.getName() + "." + attr; } + public static void setAlreadyRouted(ServerWebExchange exchange) { + exchange.getAttributes().put(GATEWAY_ALREADY_ROUTED_ATTR, true); + } + + public static boolean isAlreadyRouted(ServerWebExchange exchange) { + return exchange.getAttributeOrDefault(GATEWAY_ALREADY_ROUTED_ATTR, false); + } + public static boolean setResponseStatus(ServerWebExchange exchange, HttpStatus httpStatus) { boolean response = exchange.getResponse().setStatusCode(httpStatus); if (!response && logger.isWarnEnabled()) {