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

Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 9231ded17b fix(global): compare the Upgrade header value 
case-insensitively (#7219)
9231ded17b is described below

commit 9231ded17be6e8857c563da3fcc9d00d1a0fd8ce
Author: Sean-Walker0 <[email protected]>
AuthorDate: Sat Sep 26 17:33:40 2026 +0800

    fix(global): compare the Upgrade header value case-insensitively (#7219)
    
    DefaultShenyuContextBuilder detected the websocket rpc type with a
    case-sensitive equals against the lowercase 'websocket' literal.
    RFC 6455 requires the Upgrade header value to be compared
    case-insensitively, so standards-compliant clients sending
    'Upgrade: WebSocket' or 'Upgrade: WEBSOCKET' fell through to the
    http rpc type and the websocket plugin skipped the upgrade
    handshake.
    
    Fixes #6556
    
    Co-authored-by: Sean-Walker0 
<[email protected]>
    Co-authored-by: aias00 <[email protected]>
---
 .../plugin/global/DefaultShenyuContextBuilder.java |  3 ++-
 .../global/DefaultShenyuContextBuilderTest.java    | 28 ++++++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git 
a/shenyu-plugin/shenyu-plugin-global/src/main/java/org/apache/shenyu/plugin/global/DefaultShenyuContextBuilder.java
 
b/shenyu-plugin/shenyu-plugin-global/src/main/java/org/apache/shenyu/plugin/global/DefaultShenyuContextBuilder.java
index 072e6d365e..2ce2536f1b 100644
--- 
a/shenyu-plugin/shenyu-plugin-global/src/main/java/org/apache/shenyu/plugin/global/DefaultShenyuContextBuilder.java
+++ 
b/shenyu-plugin/shenyu-plugin-global/src/main/java/org/apache/shenyu/plugin/global/DefaultShenyuContextBuilder.java
@@ -70,7 +70,8 @@ public class DefaultShenyuContextBuilder implements 
ShenyuContextBuilder {
             return Pair.of(rpcType, new MetaData());
         }
         String upgrade = headers.getFirst(UPGRADE);
-        if (StringUtils.isNotEmpty(upgrade) && 
RpcTypeEnum.WEB_SOCKET.getName().equals(upgrade)) {
+        // RFC 6455: the Upgrade header value is case-insensitive
+        if (StringUtils.isNotEmpty(upgrade) && 
RpcTypeEnum.WEB_SOCKET.getName().equalsIgnoreCase(upgrade)) {
             return Pair.of(RpcTypeEnum.WEB_SOCKET.getName(), new MetaData());
         }
         MetaData metaData = 
MetaDataCache.getInstance().obtain(request.getURI().getRawPath());
diff --git 
a/shenyu-plugin/shenyu-plugin-global/src/test/java/org/apache/shenyu/plugin/global/DefaultShenyuContextBuilderTest.java
 
b/shenyu-plugin/shenyu-plugin-global/src/test/java/org/apache/shenyu/plugin/global/DefaultShenyuContextBuilderTest.java
index 63b4709783..d6442f0f1d 100644
--- 
a/shenyu-plugin/shenyu-plugin-global/src/test/java/org/apache/shenyu/plugin/global/DefaultShenyuContextBuilderTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-global/src/test/java/org/apache/shenyu/plugin/global/DefaultShenyuContextBuilderTest.java
@@ -21,12 +21,14 @@ import org.apache.shenyu.common.enums.RpcTypeEnum;
 import org.apache.shenyu.plugin.api.context.ShenyuContext;
 import org.apache.shenyu.plugin.api.context.ShenyuContextDecorator;
 import 
org.apache.shenyu.plugin.global.fixture.FixtureHttpShenyuContextDecorator;
+import 
org.apache.shenyu.plugin.global.fixture.FixtureWebSocketShenyuContextDecorator;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
 import org.springframework.mock.web.server.MockServerWebExchange;
 
 import java.net.InetSocketAddress;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -44,6 +46,7 @@ public final class DefaultShenyuContextBuilderTest {
     public void setUp() {
         Map<String, ShenyuContextDecorator> decoratorMap = new HashMap<>();
         decoratorMap.put("http", new FixtureHttpShenyuContextDecorator());
+        decoratorMap.put("websocket", new 
FixtureWebSocketShenyuContextDecorator());
         defaultShenyuContextBuilder = new 
DefaultShenyuContextBuilder(decoratorMap);
     }
 
@@ -57,4 +60,29 @@ public final class DefaultShenyuContextBuilderTest {
         assertNotNull(shenyuContext);
         assertEquals(RpcTypeEnum.HTTP.getName(), shenyuContext.getRpcType());
     }
+
+    @Test
+    public void testBuildWithWebSocketUpgradeHeaderValueCaseInsensitive() {
+        // RFC 6455 requires the Upgrade header value to be compared 
case-insensitively
+        for (String upgradeValue : Arrays.asList("websocket", "WebSocket", 
"WEBSOCKET", "Websocket")) {
+            MockServerWebExchange exchange = 
MockServerWebExchange.from(MockServerHttpRequest.get("http://localhost:8080/websocket";)
+                    .remoteAddress(new InetSocketAddress(8092))
+                    .header("Upgrade", upgradeValue)
+                    .header("Connection", "Upgrade")
+                    .build());
+            ShenyuContext shenyuContext = 
defaultShenyuContextBuilder.build(exchange);
+            assertEquals(RpcTypeEnum.WEB_SOCKET.getName(), 
shenyuContext.getRpcType(),
+                    "Upgrade header value '" + upgradeValue + "' must be 
detected as websocket rpc type");
+        }
+    }
+
+    @Test
+    public void testBuildWithNonWebSocketUpgradeHeaderValue() {
+        MockServerWebExchange exchange = 
MockServerWebExchange.from(MockServerHttpRequest.get("http://localhost:8080/http";)
+                .remoteAddress(new InetSocketAddress(8092))
+                .header("Upgrade", "h2c")
+                .build());
+        ShenyuContext shenyuContext = 
defaultShenyuContextBuilder.build(exchange);
+        assertEquals(RpcTypeEnum.HTTP.getName(), shenyuContext.getRpcType());
+    }
 }

Reply via email to