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

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


The following commit(s) were added to refs/heads/main by this push:
     new 56a87c2076 Review do not upgrade HTTP/1.0 PRs
56a87c2076 is described below

commit 56a87c20760f18062c15c850b7bc18b7f3489e64
Author: Mark Thomas <[email protected]>
AuthorDate: Thu Nov 5 17:37:03 2026 +0000

    Review do not upgrade HTTP/1.0 PRs
    
    Switch to only allowing upgrade for an HTTP/1.1 request
---
 java/org/apache/coyote/http11/Http11Processor.java |  2 +-
 .../tomcat/websocket/server/UpgradeUtil.java       |  6 +++-
 .../websocket/server/TestWsServerContainer.java    | 41 ++++++++++++++++++++--
 3 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/java/org/apache/coyote/http11/Http11Processor.java 
b/java/org/apache/coyote/http11/Http11Processor.java
index f249e0dbdb..5c2ae2d616 100644
--- a/java/org/apache/coyote/http11/Http11Processor.java
+++ b/java/org/apache/coyote/http11/Http11Processor.java
@@ -332,7 +332,7 @@ public class Http11Processor extends AbstractProcessor {
 
             // Has an upgrade been requested? An Upgrade header field in an 
HTTP/1.0 request must be ignored
             // (RFC 9110, section 7.8)
-            if (http11 && isConnectionToken(request.getMimeHeaders(), 
"upgrade")) {
+            if (request.protocol().equals(Constants.HTTP_11) && 
isConnectionToken(request.getMimeHeaders(), "upgrade")) {
                 // Check the protocol
                 String requestedProtocol = request.getHeader("Upgrade");
 
diff --git a/java/org/apache/tomcat/websocket/server/UpgradeUtil.java 
b/java/org/apache/tomcat/websocket/server/UpgradeUtil.java
index 9f1b17cecf..857e321b04 100644
--- a/java/org/apache/tomcat/websocket/server/UpgradeUtil.java
+++ b/java/org/apache/tomcat/websocket/server/UpgradeUtil.java
@@ -85,7 +85,7 @@ public class UpgradeUtil {
                 headerContainsToken((HttpServletRequest) request, 
Constants.UPGRADE_HEADER_NAME,
                         Constants.UPGRADE_HEADER_VALUE) &&
                 Method.GET.equals(((HttpServletRequest) request).getMethod()) 
&&
-                !"HTTP/1.0".equals(request.getProtocol()));
+                "HTTP/1.1".equals(request.getProtocol()));
     }
 
 
@@ -107,6 +107,10 @@ public class UpgradeUtil {
         // validation fails
         String key;
         String subProtocol;
+        if (!"HTTP/1.1".equals(req.getProtocol())) {
+            resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
+            return;
+        }
         if (!headerContainsToken(req, Constants.CONNECTION_HEADER_NAME, 
Constants.CONNECTION_HEADER_VALUE)) {
             resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
             return;
diff --git a/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java 
b/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java
index 8d21010096..2eee21024e 100644
--- a/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java
+++ b/test/org/apache/tomcat/websocket/server/TestWsServerContainer.java
@@ -493,7 +493,7 @@ public class TestWsServerContainer extends 
WebSocketBaseTest {
 
     @Test
     public void testUpgradeHttpToWebSocket01() throws Exception {
-        TesterHttpServletRequest request = new TesterHttpServletRequest();
+        TesterHttpServletRequest request = new UpgradeRequest("HTTP/1.1");
 
         request.setScheme("http");
 
@@ -522,7 +522,7 @@ public class TestWsServerContainer extends 
WebSocketBaseTest {
 
     @Test(expected = DeploymentException.class)
     public void testUpgradeHttpToWebSocket02() throws Exception {
-        TesterHttpServletRequest request = new TesterHttpServletRequest();
+        TesterHttpServletRequest request = new UpgradeRequest("HTTP/1.1");
 
         request.setHeader(Constants.CONNECTION_HEADER_NAME, 
Constants.CONNECTION_HEADER_VALUE);
         request.setHeader(Constants.WS_VERSION_HEADER_NAME, 
Constants.WS_VERSION_HEADER_VALUE);
@@ -540,6 +540,43 @@ public class TestWsServerContainer extends 
WebSocketBaseTest {
         container.upgradeHttpToWebSocket(request, response, sec, new 
HashMap<>());
     }
 
+
+    @Test
+    public void testUpgradeHttpToWebSocket03() throws Exception {
+        TesterHttpServletRequest request = new UpgradeRequest("HTTP/1.0");
+        TesterHttpServletResponse response = new UpgradeResponse();
+
+        WsServerContainer container = new WsServerContainer(new 
TesterServletContext());
+
+        container.upgradeHttpToWebSocket(request, response,
+                ServerEndpointConfig.Builder.create(Object.class, 
"/").build(), new HashMap<>());
+
+        Assert.assertEquals(HttpServletResponse.SC_BAD_REQUEST, 
response.getStatus());
+    }
+
+
+    private static class UpgradeRequest extends TesterHttpServletRequest {
+        private final String protocol;
+
+        UpgradeRequest(String protocol) {
+            this.protocol = protocol;
+        }
+
+        @Override
+        public String getProtocol() {
+            return protocol;
+        }
+    }
+
+
+    private static class UpgradeResponse extends TesterHttpServletResponse {
+        @Override
+        public void sendError(int status) {
+            setStatus(status);
+        }
+    }
+
+
     private static class DummyDecoder implements Decoder {
         @SuppressWarnings("unused")
         DummyDecoder(String ignoredParam) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to