Make sure subProtocols and headers are passed through.

fixes gh-59
This commit is contained in:
Spencer Gibb
2017-10-02 22:04:24 -04:00
parent c96feed9e7
commit 3431f3d87a
2 changed files with 47 additions and 11 deletions

View File

@@ -1,9 +1,12 @@
package org.springframework.cloud.gateway.filter;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.WebSocketSession;
@@ -21,6 +24,8 @@ import reactor.core.publisher.Mono;
* @author Spencer Gibb
*/
public class WebsocketRoutingFilter implements GlobalFilter, Ordered {
public static final String SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol";
private final WebSocketClient webSocketClient;
private final WebSocketService webSocketService;
@@ -48,30 +53,54 @@ public class WebsocketRoutingFilter implements GlobalFilter, Ordered {
return chain.filter(exchange);
}
return this.webSocketService.handleRequest(exchange, new ProxyWebSocketHandler(requestUrl, this.webSocketClient));
return this.webSocketService.handleRequest(exchange,
new ProxyWebSocketHandler(requestUrl, this.webSocketClient, exchange.getRequest().getHeaders()));
}
private static class ProxyWebSocketHandler implements WebSocketHandler {
private final WebSocketClient client;
private final URI url;
private final HttpHeaders headers;
private final List<String> subProtocols;
public ProxyWebSocketHandler(URI url, WebSocketClient client) {
public ProxyWebSocketHandler(URI url, WebSocketClient client, HttpHeaders headers) {
this.client = client;
this.url = url;
this.headers = headers;
List<String> protocols = headers.get(SEC_WEBSOCKET_PROTOCOL);
if (protocols != null) {
this.subProtocols = protocols;
} else {
this.subProtocols = Collections.emptyList();
}
}
@Override
public List<String> getSubProtocols() {
return this.subProtocols;
}
@Override
public Mono<Void> handle(WebSocketSession session) {
return client.execute(url, proxySession -> {
// Use retain() for Reactor Netty
Mono<Void> proxySessionSend = proxySession
.send(session.receive().doOnNext(WebSocketMessage::retain))
.log("proxySessionSend", Level.FINE);
Mono<Void> serverSessionSend = session
.send(proxySession.receive().doOnNext(WebSocketMessage::retain))
.log("sessionSend", Level.FINE);
return Mono.when(proxySessionSend, serverSessionSend).then();
return client.execute(url, this.headers, new WebSocketHandler() {
@Override
public Mono<Void> handle(WebSocketSession proxySession) {
// Use retain() for Reactor Netty
Mono<Void> proxySessionSend = proxySession
.send(session.receive().doOnNext(WebSocketMessage::retain))
.log("proxySessionSend", Level.FINE);
Mono<Void> serverSessionSend = session
.send(proxySession.receive().doOnNext(WebSocketMessage::retain))
.log("sessionSend", Level.FINE);
return Mono.when(proxySessionSend, serverSessionSend).then();
}
@Override
public List<String> getSubProtocols() {
return ProxyWebSocketHandler.this.subProtocols;
}
});
}
}

View File

@@ -45,6 +45,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
@@ -260,6 +261,9 @@ public class WebSocketIntegrationTests {
@Override
public Mono<Void> handle(WebSocketSession session) {
String protocol = session.getHandshakeInfo().getSubProtocol();
if (!StringUtils.hasText(protocol)) {
return Mono.error(new IllegalStateException("Missing protocol"));
}
WebSocketMessage message = session.textMessage(protocol);
return doSend(session, Mono.just(message));
}
@@ -270,6 +274,9 @@ public class WebSocketIntegrationTests {
@Override
public Mono<Void> handle(WebSocketSession session) {
HttpHeaders headers = session.getHandshakeInfo().getHeaders();
if (!headers.containsKey("my-header")) {
return Mono.error(new IllegalStateException("Missing my-header"));
}
String payload = "my-header:" + headers.getFirst("my-header");
WebSocketMessage message = session.textMessage(payload);
return doSend(session, Mono.just(message));