引言
在使用 Nginx 作为反向代理服务 OnlyOffice 时,发现原本应为https://ip:port/cache/...
的请求,在经过 Nginx 代理后,变成了https://ip/cache/...
。
问题描述
当 Nginx 配置如下代理 OnlyOffice 请求时:
location ~* /(8.3.0-|web-apps|cache/files) {# OnlyOffice 容器的地址和端口proxy_pass http://192.168.1.186:8050;# 设置必要的头信息proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;# WebSocket 支持(OnlyOffice 协作编辑依赖)proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_set_header X-Frame-Options "SAMEORIGIN";# 超时设置proxy_connect_timeout 7d;proxy_send_timeout 7d;proxy_read_timeout 7d;send_timeout 7d;# 缓冲设置proxy_buffering off;
}
观察到正常应该对https://ip:port/cache/files/data/3564657e6e/Editor.bin/Editor.bin?...
的请求,在实际访问时,端口号被移除,变为https://ip/cache/files/data/3564657e6e/Editor.bin/Editor.bin?...
。导致 OnlyOffice 编辑器无法下载文件并回显。
问题分析
此问题的根本原因在于 OnlyOffice 服务在生成重定向或资源链接时,依赖于请求头中的Host
和协议信息来构造返回的 URL。尽管 Nginx 配置中包含了proxy_set_header Host $host;
,但$host
变量在某些情况下并不包含端口号,从而导致后端服务生成的 URL 缺少端口。
具体来说:
$host
变量的行为:$host
变量优先取自客户端请求头中的Host
字段。- 如果客户端请求头中包含端口(例如
Host: example.com:8443
),则$host
会包含端口。 - 然而,如果客户端通过域名访问且使用标准端口(如 HTTPS 的 443 端口),浏览器通常会省略
Host
头中的端口号(例如Host: example.com
而非Host: example.com:443
)。在这种情况下,Nginx 的$host
变量也不会包含端口。
- OnlyOffice 的依赖:当 OnlyOffice 后端服务接收到
Host: your-domain.com
(不带端口)的请求头时,它会认为当前服务的访问地址不包含端口,因此在生成回调、资源链接或重定向 URL 时,也会省略端口,最终导致前端请求的 URL 丢失端口。
解决方案:强制在Host
头中保留端口号
为解决此问题,需要确保传递给 OnlyOffice 后端的Host
头中始终包含端口号,即使该端口是标准端口(如 443)。这可以通过修改 Nginx 的proxy_set_header Host
指令来实现。
修改方式
将 Nginx 配置中的proxy_set_header Host $host;
修改为proxy_set_header Host $host:$server_port;
。
location ~* /(8.3.0-|web-apps|Editor.bin) {proxy_pass http://192.168.1.186:8050;# 关键修改:强制设置 Host 头,包含当前服务器监听的端口号proxy_set_header Host $host:$server_port;# 如果希望固定某个特定端口(例如 8443),也可以这样写:# proxy_set_header Host $host:8443;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;# WebSocket 支持(OnlyOffice 协作编辑依赖)proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_set_header X-Frame-Options "SAMEORIGIN"; # 允许嵌套# 超时设置proxy_connect_timeout 7d;proxy_send_timeout 7d;proxy_read_timeout 7d;send_timeout 7d;# 缓冲设置proxy_buffering off;
}
关键指令解释
下表详细解释了 Nginx 中与Host
头相关的几个变量和指令:
指令/变量 | 说明 |
---|---|
$host |
通常是客户端请求头中Host 字段的值。如果客户端请求的是标准端口(如 80 或 443),浏览器通常会省略端口,此时$host 也不包含端口。 |
$http_host |
等同于$host 。在未设置Host 请求头时,此变量可能为空。 |
$server_port |
Nginx 服务器当前监听的端口号。例如,如果 Nginx 监听 8443 端口,则$server_port 的值为8443 。 |
proxy_set_header Host $host:$server_port; |
推荐的解决方案。此指令强制将Host 请求头设置为客户端请求的域名(或 IP)与 Nginx 监听端口的组合。这样,即使客户端请求的Host 头不带端口,后端 OnlyOffice 服务也能收到完整的Host:Port 信息,从而生成正确的带端口的 URL。 |
总结
OnlyOffice 在 Nginx 代理下出现 URL 端口丢失的问题,其核心在于 Nginx 的$host
变量在某些情况下不包含端口信息,导致 OnlyOffice 后端生成了错误的资源链接。通过将proxy_set_header Host $host:$server_port;
添加到 Nginx 配置中,可以强制将完整的Host:Port
信息传递给 OnlyOffice 后端,从而解决此问题。