This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 5a60314251f211d73937fb9ce0f6a391f4ab3d11
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Jun 23 11:55:56 2025 +0100

    Always call Configurator.afterResponse() regardless of success/failure
---
 java/org/apache/tomcat/websocket/WsWebSocketContainer.java | 7 +++++--
 webapps/docs/changelog.xml                                 | 6 ++++++
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java 
b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
index 3390c8dc1d..faef999e71 100644
--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
+++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
@@ -80,6 +80,8 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
     private static final byte[] ROOT_URI_BYTES = 
"/".getBytes(StandardCharsets.ISO_8859_1);
     private static final byte[] HTTP_VERSION_BYTES = " 
HTTP/1.1\r\n".getBytes(StandardCharsets.ISO_8859_1);
 
+    private static final HandshakeResponse EMPTY_HANDSHAKE_RESPONSE = new 
WsHandshakeResponse();
+
     private volatile AsynchronousChannelGroup asynchronousChannelGroup = null;
     private final Object asynchronousChannelGroupLock = new Object();
 
@@ -275,6 +277,7 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
         Transformation transformation = null;
         AsyncChannelWrapper channel = null;
 
+        HandshakeResponse handshakeResponse = EMPTY_HANDSHAKE_RESPONSE;
         try {
             // Open the connection
             Future<Void> fConnect = socketChannel.connect(sa);
@@ -375,8 +378,7 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
                             sm.getString("wsWebSocketContainer.invalidStatus", 
Integer.toString(httpResponse.status)));
                 }
             }
-            HandshakeResponse handshakeResponse = 
httpResponse.handshakeResponse();
-            
clientEndpointConfiguration.getConfigurator().afterResponse(handshakeResponse);
+            handshakeResponse = httpResponse.handshakeResponse();
 
             // Sub-protocol
             List<String> protocolHeaders = 
handshakeResponse.getHeaders().get(Constants.WS_PROTOCOL_HEADER_NAME);
@@ -419,6 +421,7 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
                 | URISyntaxException | AuthenticationException e) {
             throw new 
DeploymentException(sm.getString("wsWebSocketContainer.httpRequestFailed", 
path), e);
         } finally {
+            
clientEndpointConfiguration.getConfigurator().afterResponse(handshakeResponse);
             if (!success) {
                 if (channel != null) {
                     channel.close();
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 770acaaacc..45d060ff3c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -263,6 +263,12 @@
         <code>getUserX509CertificateChain()</code> that provides the client
         certificate chain, if present, during the WebSocket handshake. (markt)
       </add>
+      <fix>
+        Implement the clarification in WebSocket 2.3 that the method
+        <code>ClientEndpointConfig.Configurator.afterResponse()</code> must be
+        called after every WebSocket handshake regardless of whether the
+        handshake is successful or not. (markt)
+      </fix>
       <!-- Entries for backport and removal before 12.0.0-M1 below this line 
-->
     </changelog>
   </subsection>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to