eclipse-vertx / vert.x

Vert.x is a tool-kit for building reactive applications on the JVM
http://vertx.io
Other
14.25k stars 2.07k forks source link

RSV != 0 and no extension negotiated, RSV:4 #4956

Open HK-hub opened 10 months ago

HK-hub commented 10 months ago

Questions

I used Vert.x to make a proxy server that mimics Nginx (mini nginx). On the way to implementing the proxy WebSocket, using Postman as the client to connect to the WebSocket(port 9090) proxy declared in ProxyVerticle written by Vert.x, you can successfully connect to the real server (port 8080) through the proxy. And I can send the message to the proxy server through Postman's WebSocket, and the proxy server can successfully send the message to the real server, but if I send the message through the real server, the following exception will appear. If I connect to the real server directly on port 8080 via Postman, the real server can send and receive messages. Summary: My direct connection to the real server through Postman worked fine, but if I made a WebSocket connection through the proxy server then the real server could only receive messages, and the following exception would occur if the message was sent.

[vert.x-eventloop-thread-1] ERROR io.vertx.core.net.impl.ConnectionBase -- RSV != 0 and no extension negotiated, RSV:4
io.netty.handler.codec.http.websocketx.CorruptedWebSocketFrameException: RSV != 0 and no extension negotiated, RSV:4
    at io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.protocolViolation(WebSocket08FrameDecoder.java:427)
    at io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.protocolViolation(WebSocket08FrameDecoder.java:423)
    at io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.decode(WebSocket08FrameDecoder.java:197)
    at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:529)
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:468)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:1583)

Version

this is my Maven project's pom.xml : Vert.x version is 4.4.6

<properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <vertx.version>4.4.6</vertx.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>${vertx.version}</version>
        </dependency>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-web</artifactId>
            <version>${vertx.version}</version>
        </dependency>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-web-client</artifactId>
            <version>${vertx.version}</version>
        </dependency>
    </dependencies>

I use JDK 21 , and Vert.x version is 4.4.6

Context

I used Vert.x to make a proxy server that mimics Nginx (mini nginx). When you are implementing the WebSocket proxy function, you declare the WebSocket function in the real server, and then proxy the real server WebSocket function through the proxy server. Then connect to the proxy server through Postman. However, the real server can only receive messages, and the above exception occurs if you want to write a message. I searched for information on the Internet and told me that Netty version 4.1.100.Final had already solved this problem. However, the Netty dependency underlying the Vert.x version I used at the beginning is 4.4.4 or 4.4.6 is already 4.1.100.Final, and this problem still exists, and I tried to reduce the Vert.x version to 4.1.x

Do you have a reproducer?

the project repository link is mini-nginx and the proxy server is ProxyVerticle

and the real server is ServerVerticle

I use WalkLauncher to publish ProxyVerticle and the main method parameters are as follows:

run com.hk.walk.proxy.ProxyVerticle -conf src/main/resources/config.json

the config properties is a json file. The '/chat' path block on the 'Upstream' property about the proxy side's WebSocket configuration

Steps to reproduce

  1. use command git clone https://github.com/HK-hub/mini-nginx to clone my repository
  2. Use an IDE such as IDEA to open my Maven project and import the dependencies
  3. Set the args of WalkLuncher's main function to: run com.hk.walk.proxy.ProxyVerticle -conf src/main/resources/config.json and run it
  4. Use HTTP client tools such as Postman to connect to the WebSocket address of the proxy server:ws://localhost:9090/chat
  5. Next you can see that the WebSocket connection succeeded, but was disconnected again because of the above exception

Extra

coding4m commented 10 months ago

Try this

            HttpClientOptions options = new HttpClientOptions();
            options.setDefaultHost(host).setDefaultPort(port)
                    .setKeepAlive(true)
                    .setTryUsePerFrameWebSocketCompression(true);
            HttpClient client = vertx.createHttpClient(options);

on https://github.com/HK-hub/mini-nginx/blob/master/src/main/java/com/hk/walk/config/Upstream.java

HK-hub commented 10 months ago

Try this

            HttpClientOptions options = new HttpClientOptions();
            options.setDefaultHost(host).setDefaultPort(port)
                    .setKeepAlive(true)
                    .setTryUsePerFrameWebSocketCompression(true);
            HttpClient client = vertx.createHttpClient(options);

on https://github.com/HK-hub/mini-nginx/blob/master/src/main/java/com/hk/walk/config/Upstream.java 大佬,看起来应该可以了,理论上是不是这个有header头控制,我只要添加对应的header头其实就能解决问题了。