我对 Nginx 代理有特殊需求
- 我在主 URL 下有一个全新的 JS 应用程序(+ nginx)
new.example.com
,还有一个在不同的 URL 上运行的旧应用程序old.example.com
- 我需要为我的新应用处理搜索引擎的预渲染(我正在使用prerendering nginx 官方脚本作为基础)。旧应用程序不需要预渲染(实际上它现在充当我的预渲染器)
- 当用户输入 www.example.com 时,他会访问我的 nginx 代理,该代理需要
- 代理
/admin
至old.example.com/admin
- 将所有机器人请求代理到预渲染器
- 默认代理至
new.example.com
- 代理
为了使事情简单化,我有代表每个应用程序的@location块(但这可能与其他应用程序不兼容,请告诉我)
location @newapp { proxy_pass http://new.example.com:8080; } location @oldapp { proxy_pass http://old.example.com:8080; }
现在,由于我的新应用正在开发中,我希望 URL/admin
重定向到我的旧应用。我在网上找到了一个技巧,使用 try_files 和 Maintenance.html 文件
location /admin { try_files /maintenance.html @oldapp; }
现在事情也变得严重了 - 我的新应用程序需要预渲染 - 我的旧应用程序不需要预渲染,并且在需要元数据时用作后备 - 现在我没有预渲染应用程序(我稍后会安装/设置 prerenderer.io)所以我使用我的旧应用程序作为机器人引擎的预渲染器
location @prerenderer {
try_files /maintenance.html @oldapp # will later be changes to prerenderer.io
}
# in the core nginx server block
server {
...
set $prerender 0;
# [all bot/img logic that may set prerender to 1][1]
}
此外,我还必须编辑我的@newapp以强制切换到@prerenderer
location @newapp {
if ($prerender = 1) {
try_files /maintenance.html @prerenderer;
}
if ($prerender = 0) {
try_files /maintenance.html @newapp;
}
}
但有了这个,我得到了几个 nginx 错误,我不确定我被允许或不允许做什么
nginx:[emerg]此处不允许使用“try_files”指令
看起来 nginx 不喜欢try_files
在一个if
块中。
您将如何编写 nginx conf 文件?
我的完整 nginx 配置文件如下
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
access_log /var/log/nginx/www.example.com.log;
auth_basic "Dev's Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# https://gist.github.com/thoop/8165802
set $prerender 0;
if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
set $prerender 1;
}
if ($args ~ "_escaped_fragment_") {
set $prerender 1;
}
if ($http_user_agent ~ "Prerender") {
set $prerender 0;
}
if ($uri ~* "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff|svg|eot)") {
set $prerender 0;
}
#resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
resolver 8.8.8.8;
# Defaults map to new APP EXCEPT if prerendering needed
location / {
if ($prerender = 1) {
try_files /maintenance.html @prerenderer;
}
if ($prerender = 0) {
try_files /maintenance.html @oldapp;
}
}
# Many Static pages not available => mapped to old app
location ~ /(privacy|faq|about_us|terms|press|legal) {
try_files /maintenance.html @oldapp;
}
# Admin stuff => old app
location /company/admin/ {
try_files /maintenance.html @oldapp;
}
location @prerenderer {
# For now old app, will use prerenderer.io later
try_files /maintenance.html @oldapp
}
location @newapp {
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 Host $http_host;
proxy_set_header X-NginX-Proxy true;
if ($prerender = 1) {
try_files /maintenance.html @prerenderer;
}
if ($prerender = 0) {
proxy_pass http://new.example.com:8080;
}
}
location @oldapp {
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 Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass https://old.example.com;
proxy_redirect off;
}
#ssl stuff here
client_max_body_size 4G;
keepalive_timeout 10;
}
答案1
发生该错误的原因是块try_files
内不允许if
。
我将尝试使用以下指令来实现后端的选择map
:
map $http_user_agent $render {
default $argcheck;
"~* (baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator)" old.example.com;
}
map $args $argcheck {
default oldapp;
~_escaped_fragment_ prerender;
}
通过这两个映射,您将获得一个变量,当所有指定的规则均不匹配,或者用户代理匹配或查询参数包含定义的字符串时,$render
该变量将包含。oldapp
prerender
我对这部分不是 100% 确定,但是您可以像这样使用变量:
location / {
try_files /maintenance.html @$render;
}
这样你就可以避免以下if
语句,是邪恶的。