给定用户代理的 nginx proxy_pass

给定用户代理的 nginx proxy_pass

我有一个使用 nginx 的网站,该网站几乎对所有请求都返回 index.html(单页 React 应用)。几乎任何路径(例如/some/arcticle)的任何请求也将返回index.html,并且 React 应用(React Router)会将路径转换为 ​​API 调用。这就是它的工作原理,并且无法更改(网站很大,工作量太大,而且无论如何我也没有能力更改这一点)。

这些请求应该有两个例外:

  1. 所有以 /api/* 路径开头的请求都会传递到上游(应用服务器)。因此,不同的后端将处理所有实际的 API 请求。
  2. 另一个例外应该是 Facebook 外部点击。应用服务器上的 /api/open_graph 下有一个不同的端点。例如,/api/open_graph 应该添加到原始路径的前面。该端点返回实际内容(而不是没有实际内容的常见单页 React 应用程序)。格式也不同 - 普通 API 调用通常返回 JSON 数据,但 open_graph 端点返回简单的 HTML。

nginx 配置示例:

upstream www {
    # ...
}

server {
    # ...

    # Use /api/open_graph on the upstream for facebook external hits
    if ($http_user_agent ~* "^facebookexternalhit.*$") {
        rewrite ^/(.*)$ /api/open_graph/$1 permanent;
    }

    # API requests will go to upstream
    location ~ ^/api/ {
        proxy_pass          http://www;
        proxy_read_timeout  90;
        proxy_redirect      http://www https://example.com;
    }

    # All other requests use a react app,
    # react router handles all further requests
    location / {
        index index.html;
        error_page 404 =200 /index.html;
    }

}

上述配置的工作原理如下:

# curl -A "facebookexternalhit" -s -D - -o /dev/null https://example.com/article1
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Wed, 20 Oct 2021 08:14:13 GMT
Content-Type: text/html
Content-Length: 162
Location: https://example.com/api/open_graph/article1
Connection: keep-alive
Strict-Transport-Security: max-age=31536000
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN

这几乎是好的,除了 facebook graph api 不处理重定向。(谁知道为什么?)。因此,不应重定向到/api/open_graph/*服务器,而应直接连接上游并转发请求。

但我不知道该怎么做?最简单的解决方案是:

    # Use /api/open_graph on the upstream for facebook external hits
    if ($http_user_agent ~* "^facebookexternalhit.*$") {
        rewrite ^/(.*)$ /api/open_graph/$1 permanent;
        proxy_pass          http://www;
        proxy_read_timeout  90;
        proxy_redirect      http://www https://example.com;
    }

但它不起作用,因为proxy_pass只能在 内部使用location。它不能在 内部使用if。如果我尝试该配置,则我得到:

nginx: [emerg] "proxy_pass" directive is not allowed here in /etc/nginx/sites-enabled/example-www:62
nginx: configuration file /etc/nginx/nginx.conf test failed

我可能可以更改上游的程序代码(例如,在那里为用户代理添加过滤器),但这会非常困难。

nginx 中有没有解决这个问题的方法?

该问题与以下内容相关:nginx - user_agent 上的 proxy_pass但这对我也不起作用(引发错误)

相关内容