Featured image of post Nginx 反向代理 NoVNC

Nginx 反向代理 NoVNC

NoVNC 的网页端涉及到两个地址,分别是前端网页所处的 /,以及用于传输数据的 WebSocket 连接 /websockify。用 Nginx 反向代理 NoVNC 服务需要分别处理这两个地址。

将 NoVNC 绑定在 /

将 NoVNC 绑定在根目录非常简单,不需要单独处理 ws 连接,直接将 proxy_pass 设置为 NoVNC 的端口即可并为 ws 连接转发升级连接的请求头即可:

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  location / {
    proxy_pass http://localhost:7900/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }
}

将 NoVNC 绑定在其他任意路径上

因为 /websockify 和其他资源处在不同的路径上,并且这项配置是写在 NoVNC 配置里的(而不是根据前端网页的位置自动解析的),因此需要对这个路径做一些特殊处理。下面以将 NoVNC 绑定到 /application 为例介绍几种不同的处理方式:

1. 修改 NoVNC 的配置

你可以在界面左侧的配置中点击齿轮-Advanced-WebSocket,点击 Path 输入框将 ws 连接路径修改为 /application/websockify/(结尾的斜线是必要的)。但是这种方式每次打开都需要修改。

你也可以把 path=/application/websockify/ 放在 URL 的查询参数列表里,并让浏览器帮你记住。

2. 将 /websockify 单独绑定

这个方法比较直观,直接添加一个 location /websockify(结尾无斜线),并仿照上述绑定规则填上即可。缺点是该方法会额外占用一个 /websockify 路径,并且不可修改。详细配置如下:

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  location /application/ { # slash is required
    proxy_pass http://localhost:7900/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }

  location /websockify { # no slash
    proxy_pass http://localhost:7900/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }
}

3. 用一些 workaround 将/websockify 绑在目标路径上

前面提到可以通过将 path=/application/websockify/ 放在 URL 的查询参数列表里实现配置 NoVNC 的 ws 连接,我尝试使用 Nginx 的 rewrite 将该查询自动补全到 URL 的后面,这样对前端和用户来说都是无感的。但是无论我怎么尝试,在后台都能看到参数列表是被成功 rewritten 的,但是 NoVNC 就是识别不到,这就很奇怪,按理 NoVNC 应该是拿不到原始请求的,它无法通过原始请求判断参数列表,其中的原因有点搞不清楚。我的处理方式是在 rewrite 语句最后加上 redirect flag,让浏览器显示请求被跳转到了包含查询列表的链接,这样一来就跟替用户在地址栏中填入 path 没有区别了,实际用起来也蛮爽的。代码如下:

map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  location /application/ { # slash is required
    proxy_pass http://localhost:7900/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }

  location /application/websockify/ { # if here has trailing slash, then rewrite sentence must have one
    proxy_pass http://localhost:7900/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }

  location /application-bot/ {
    rewrite ^/application-bot/(.*)$ /application/$1?path=application/websockify/ redirect;
    proxy_pass http://localhost:7900/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }

}

这样当用户访问 /application-bot 的时候就会自动跳转到 /application/$1?path=application/websockify/ 了。

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy