首页 > 解决方案 > NGINX 从 proxy_pass 响应中读取正文

问题描述

我有两台服务器:

  1. NGINX(它将文件ID交换到文件路径)
  2. Golang(它接受文件 id 并返回它的路径)

例如:当浏览器客户端向 NGINX 发出请求时https://example.com/file?id=123,NGINX 应该将此请求代理到 Golang 服务器https://go.example.com/getpath?file_id=123,Golang 服务器会将响应返回给 NGINX:

{
  data: {
    filePath: "/static/..."
  },
  status: "ok"
}

然后 NGINX 应该从 filePath 获取值并从该位置返回文件。

所以问题是如何在 NGINX 中读取响应(获取文件路径)?

标签: nginxluaproxypass

解决方案


我假设您是软件开发人员,并且您可以完全控制您的应用程序,因此无需在此处强制将方形钉插入圆孔。

不同类型的反向代理支持ESI(Edge Side Includes)技术,允许开发人员用静态文件的内容或上游服务器的响应体替换响应体的不同部分。

Nginx 也有这样的技术。它被称为SSI(服务器端包含)

location /file {
    ssi on;
    proxy_pass http://go.example.com;
}

您的上游服务器可以生成带有内容的正文,<!--# include file="/path-to-static-files/some-static-file.ext" -->nginx 将用文件的内容替换这个 in-body 指令

但是你提到了流媒体......

这意味着文件将具有任意大小,并且使用SSI 构建响应肯定会占用宝贵的 RAM资源,因此我们需要一个计划 #B

有一种“足够好”的方法可以将大文件提供给客户端,而不向客户端显示文件的静态位置。您可以使用 nginx 的错误处理程序根据上游服务器提供的信息来处理静态文件。例如,上游服务器可以发回重定向 302,其中 Location 头字段包含文件的真实文件路径。此响应不会到达客户端,而是馈送到错误处理程序中。

下面是一个配置示例:

location /file {
    error_page 302 = @service_static_file;
    proxy_intercept_errors on;
    proxy_set_header Host            $host;
    proxy_pass http://go.example.com;
}

location @service_static_file {
    root /hidden-files;
    try_files $upstream_http_location 404.html;
}

使用这种方法,您将能够在不超载系统的情况下提供文件,同时可以控制将文件提供给谁。

为此,您的上游服务器应以状态 302 和典型的“位置:”字段响应,并且 nginx 将使用位置内容在静态文件的“新”根目录中查找文件。

此方法之所以为“足够好”类型(而不是完美),是因为它不支持部分请求(即 Range: bytes ...)


推荐阅读