我有一个使用 nginx 的网站,该网站几乎对所有请求都返回 index.html(单页 React 应用)。几乎任何路径(例如/some/arcticle
)的任何请求也将返回index.html
,并且 React 应用(React Router)会将路径转换为 API 调用。这就是它的工作原理,并且无法更改(网站很大,工作量太大,而且无论如何我也没有能力更改这一点)。
这些请求应该有两个例外:
- 所有以 /api/* 路径开头的请求都会传递到上游(应用服务器)。因此,不同的后端将处理所有实际的 API 请求。
- 另一个例外应该是 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但这对我也不起作用(引发错误)