首页 > 解决方案 > 通过 Ingress nginx 的独立 WebSocket 客户端失败

问题描述

在 Hosted Rancher Kubernetes 集群中,我有一个公开 websocket 服务(Spring SockJS 服务器)的服务。由于入口规则,此服务暴露在外部:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: myIngress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600s"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600s"
    nginx.ingress.kubernetes.io/enable-access-log: "true"
spec:
  rules:
    - http:
        paths:
        - path: /app1/mySvc/
          backend:
            serviceName: mySvc
            servicePort: 80

Web 应用程序通过入口 nginx 连接到 Web 套接字服务,并且工作正常。加载的js脚本为:

    var socket = new SockJS('ws');
    stompClient = Stomp.over(socket);

    stompClient.connect({}, onConnected, onError);

相反,独立客户端(js 或 python)不起作用,因为它们返回 400 http 错误。

例如,这是 curl 发送的请求和 nginx 的响应:

curl  --noproxy '*' --include \
     --no-buffer \
     -Lk \
--header "Sec-WebSocket-Key: l3ApADGCNFGSyFbo63yI1A==" \
--header "Sec-WebSocket-Version: 13" \
--header "Host: ingressHost" \
--header "Origin: ingressHost" \
--header "Connection: keep-alive, Upgrade" \
--header "Upgrade: websocket" \
--header "Sec-WebSocket-Extensions: permessage-deflate" \
--header "Sec-WebSocket-Protocol: v10.stomp, v11.stomp, v12.stomp" \
--header "Access-Control-Allow-Credentials: true" \
https://ingressHost/app1/mySvc/ws/websocket


HTTP/2 400
date: Wed, 20 Nov 2019 14:37:36 GMT
content-length: 34
vary: Origin
vary: Access-Control-Request-Method
vary: Access-Control-Request-Headers
access-control-allow-origin: ingressHost
access-control-allow-credentials: true
set-cookie: JSESSIONID=D0BC1540775544E34FFABA17D14C8898; Path=/; HttpOnly
strict-transport-security: max-age=15724800; includeSubDomains

Can "Upgrade" only to "WebSocket".

为什么它适用于浏览器而不是独立客户端?

谢谢

标签: nginxkuberneteswebsocketranchernginx-ingress

解决方案


我在 Spring 应用程序中激活了跟踪,并使用 curl 调用:

o.s.w.s.s.s.DefaultHandshakeHandler      : Handshake failed due to invalid Upgrade header: null

因此,似乎 nginx 删除了 Upgrade 标头!

使用浏览器客户端进行测试时,标头存在于 Spring Applicaton 中并且可以正常工作。


推荐阅读