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());
+ }
}