spring-cloud / spring-cloud/spring-cloud-gateway

WebSocketHandshakeException Invalid handshake response getStatus: 403 Forbidden

Open
#3,198 16 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

waiting-for-triage
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

Hi everyone, I want to use spring-cloud-gateway for reverse proxy of code-server. But I encountered the following error.

io.netty.handler.codec.http.websocketx.WebSocketHandshakeException: Invalid handshake response getStatus: 403 Forbidden
        at io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker13.verify(WebSocketClientHandshaker13.java:274) ~[netty-codec-http-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker.finishHandshake(WebSocketClientHandshaker.java:302) ~[netty-codec-http-4.1.51.Final.jar!/:4.1.51.Final]
        at reactor.netty.http.client.WebsocketClientOperations.onInboundNext(WebsocketClientOperations.java:118) ~[reactor-netty-0.9.10.RELEASE.jar!/:0.9.10.RELEASE]
        at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:96) [reactor-netty-0.9.10.RELEASE.jar!/:0.9.10.RELEASE]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) [netty-codec-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) [netty-codec-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:383) [netty-codec-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:354) [netty-codec-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:311) [netty-codec-http-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:221) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:241) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1405) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:262) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:248) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:901) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:818) [netty-transport-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164) [netty-common-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472) [netty-common-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:384) [netty-transport-native-epoll-4.1.51.Final-linux-x86_64.jar!/:4.1.51.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) [netty-common-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-common-4.1.51.Final.jar!/:4.1.51.Final]
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-common-4.1.51.Final.jar!/:4.1.51.Final]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_202]

The docker command of the code server I use is as follows.

docker run -it --name code-server --rm  -p 40001:8080    codercom/code-server:latest
# docker exec -it code-server bash 
# cat /home/coder/.config/code-server/config.yaml

The version of spring-cloud-gateway is as follows

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
   </dependency>

The configuration of the gateway is as follows.

server:
  port: 30000
spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      filter:
        remove-non-proxy-headers:
          headers:
      httpclient:
        websocket:
          max-frame-payload-length: 3000000 
      routes:
        - id:  docker-app
          uri: http://192.168.3.60:80
          predicates:
            - Path=/app/**
        - id: vscode-cloud
          uri: http://192.168.3.60:40001
          predicates:
            - Path=/vscode/**
          filters:
            - RewritePath=/vscode/(?<segment>.*), /$\{segment}

When I access http://192.168.3.60:30000/vscode/?folder=/home/coder, the above error appears in the log of spring-cloud-gateway.

The above port 80 is the reverse proxy of nginx and can be accessed normally.

location /app/ {
      add_header X-debug-message "A static file was served" always;
      add_header aaa "$request_uri";
      if ($request_uri ~ /app/(.+)) {
            set $rightUrl $1;
      }
      add_header bbb "$rightUrl";
      proxy_pass http://192.168.3.60:$rightUrl;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      proxy_set_header Host $host;
      rewrite ^/app/$rightUrl(.*)$ /$1 break;
}

http://192.168.3.60/app/40001/?folder=/home/coder

But when I use spring-cloud-gateway to proxy nginx 80, I continue to report the above error.
http://192.168.3.60:30000/app/40001/?folder=/home/coder

please help !

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the WebSocket request through the spring-cloud-gateway route for /vscode/** and compare it with the direct code-server and nginx paths described in the issue. Inspect the RewritePath configuration, proxy headers, and 403 handshake response; done means the cause is isolated and the gateway route either completes the handshake or documents the required configuration.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, java, nginx, spring-boot
Domain
api, backend, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.