Skip to content

反向代理(URL 路径前缀)

在反向代理后将 Potato 部署到子路径下,例如 https://host/app1/。配置部署 URL 前缀,使静态资源、标注操作和实时流在挂载路径下都能正确解析。

Potato 可以在反向代理后以 URL 子路径运行,例如 https://host/app1/,当多台内部服务器共享同一个公网 HTTPS 端点时,这种方式很常见:

text
https://host/app1/  ->  http://127.0.0.1:8000/
https://host/app2/  ->  http://127.0.0.1:8001/

标注界面通过根相对 URL(/static/.../updateinstance/annotate/media/...)加载静态资源并执行操作。当 Potato 挂载到 /app1 下时,这些 URL 否则会相对公网根目录解析,表现为 CSS 和 JS 出现 404、界面隐藏,或自动保存失败并提示“annotations not saved”。部署前缀无需针对每个站点修改 nginx 即可解决此问题。

工作原理

下面两种方案都会设置 WSGI 的 SCRIPT_NAME,Potato 将其作为唯一可信来源,用于服务端渲染的 url_for(...) 输出以及暴露给浏览器、作为 window.config.url_prefix 的客户端前缀。该前缀会包裹 fetch()sendBeacon()EventSource 以及根相对的 href/action/src 属性。当未设置前缀时,SCRIPT_NAME 为空,不会有任何变化,因此对于普通的 potato start 运行这是一个空操作。

方案 A — POTATO_PROXY_FIX(代理发送转发头)

当你掌控代理且它能够发送转发头时使用此方案。Potato 会启用 Werkzeug 的 ProxyFix,它会逐请求读取 X-Forwarded-Prefix(以及 -Proto/-Host/-For)。

bash
export POTATO_PROXY_FIX=1
potato start config.yaml -p 8000

nginx,剥离前缀并将其作为头转发:

nginx
location /app1/ {
    proxy_pass         http://127.0.0.1:8000/;   # trailing slash strips /app1/
    proxy_set_header   Host              $host;
    proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;
    proxy_set_header   X-Forwarded-Prefix /app1;
}

ProxyFix 信任转发头。仅当应用只能通过受信任的代理访问时才启用 POTATO_PROXY_FIX。如果内部端口也可被直接访问,客户端便可能伪造 X-Forwarded-Prefix-Host,从而污染生成的 URL。

方案 B — POTATO_URL_PREFIX(代理配置无法更改)

当你无法添加转发头但已知公网挂载路径时使用此方案。Potato 会自行将前缀注入 SCRIPT_NAME

bash
export POTATO_URL_PREFIX=/app1
potato start config.yaml -p 8000

代理仍必须在转发前剥离前缀,以便 Flask 收到无前缀的路径,例如 /static/styles.css

nginx
location /app1/ {
    proxy_pass       http://127.0.0.1:8000/;     # trailing slash strips /app1/
    proxy_set_header Host $host;
}

如果两个变量都已设置,逐请求转发的前缀优先,POTATO_URL_PREFIX 作为后备。

实时流(服务器发送事件)

实时代理和实时编码查看器使用 SSE。URL 前缀会自动应用,但 SSE 还需要代理在流位置上禁用缓冲,否则事件会被滞留:

nginx
location /app1/api/ {
    proxy_pass            http://127.0.0.1:8000/api/;
    proxy_set_header      Host $host;
    proxy_buffering       off;
    proxy_read_timeout    3600s;
}

验证

  1. 加载 https://host/app1/,确认 CSS 和 JS 加载且没有 404。
  2. 进行一次标注,确认其自动保存。
  3. 导航“下一个/上一个”,确认媒体和数据正常渲染。
  4. 如果使用实时代理评估,确认流连接并更新。

注意事项与限制

  • 显示的标注内容内部的根相对链接也会被加上前缀。打算指向公网根目录的内容作者应使用绝对 URL。
  • 通过 pip 安装的部署依赖打包的静态资源;请确保你的构建包含嵌套的 static/ 目录。

相关内容

有关实现细节,请参阅源文档