Mark response as complete before WebSocket upgrade
Prior to this commit, some WebSocket `RequestUpgradeStrategy` reactive implementations would prevent the application from writing HTTP headers and cookies to the response. For Reactor Netty and Undertow, handling the upgrade and starting the WebSocket communication marks the response status and headers as sent and the application cannot update HTTP response headers after that. This commit ensures that the `RequestUpgradeStrategy` implementations mark the responses as "complete", so that headers are written before we delegate to the server implementation. Fixes gh-24475
This commit is contained in:
@@ -103,15 +103,15 @@ public class ReactorNettyRequestUpgradeStrategy implements RequestUpgradeStrateg
|
||||
HttpServerResponse reactorResponse = getNativeResponse(response);
|
||||
HandshakeInfo handshakeInfo = handshakeInfoFactory.get();
|
||||
NettyDataBufferFactory bufferFactory = (NettyDataBufferFactory) response.bufferFactory();
|
||||
|
||||
return reactorResponse.sendWebsocket(subProtocol, this.maxFramePayloadLength, this.handlePing,
|
||||
(in, out) -> {
|
||||
ReactorNettyWebSocketSession session =
|
||||
new ReactorNettyWebSocketSession(
|
||||
in, out, handshakeInfo, bufferFactory, this.maxFramePayloadLength);
|
||||
URI uri = exchange.getRequest().getURI();
|
||||
return handler.handle(session).checkpoint(uri + " [ReactorNettyRequestUpgradeStrategy]");
|
||||
});
|
||||
return response.setComplete()
|
||||
.then(Mono.defer(() -> reactorResponse.sendWebsocket(subProtocol, this.maxFramePayloadLength, this.handlePing,
|
||||
(in, out) -> {
|
||||
ReactorNettyWebSocketSession session =
|
||||
new ReactorNettyWebSocketSession(
|
||||
in, out, handshakeInfo, bufferFactory, this.maxFramePayloadLength);
|
||||
URI uri = exchange.getRequest().getURI();
|
||||
return handler.handle(session).checkpoint(uri + " [ReactorNettyRequestUpgradeStrategy]");
|
||||
})));
|
||||
}
|
||||
|
||||
private static HttpServerResponse getNativeResponse(ServerHttpResponse response) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -43,10 +43,11 @@ import org.springframework.web.reactive.socket.server.RequestUpgradeStrategy;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* A {@link RequestUpgradeStrategy} for use with Undertow.
|
||||
*
|
||||
* A {@link RequestUpgradeStrategy} for use with Undertow.
|
||||
*
|
||||
* @author Violeta Georgieva
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Brian Clozel
|
||||
* @since 5.0
|
||||
*/
|
||||
public class UndertowRequestUpgradeStrategy implements RequestUpgradeStrategy {
|
||||
@@ -63,16 +64,12 @@ public class UndertowRequestUpgradeStrategy implements RequestUpgradeStrategy {
|
||||
|
||||
HandshakeInfo handshakeInfo = handshakeInfoFactory.get();
|
||||
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
|
||||
|
||||
try {
|
||||
DefaultCallback callback = new DefaultCallback(handshakeInfo, handler, bufferFactory);
|
||||
new WebSocketProtocolHandshakeHandler(handshakes, callback).handleRequest(httpExchange);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return Mono.error(ex);
|
||||
}
|
||||
|
||||
return Mono.empty();
|
||||
return exchange.getResponse().setComplete()
|
||||
.then(Mono.fromCallable(() -> {
|
||||
DefaultCallback callback = new DefaultCallback(handshakeInfo, handler, bufferFactory);
|
||||
new WebSocketProtocolHandshakeHandler(handshakes, callback).handleRequest(httpExchange);
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
|
||||
private static HttpServerExchange getNativeRequest(ServerHttpRequest request) {
|
||||
|
||||
Reference in New Issue
Block a user