nginx reverse_proxy与多个服务器/位置块和预渲染

我有一个Nginx代理的特定需求

  • 我在主urlnew.example.com下有一个全新的JS应用程序(+ nginx),以及一个运行在不同url上的旧应用程序old.example.com
  • 我需要为我的新应用程序处理search引擎的预渲染(我使用prerender nginx官方脚本作为基础)。 旧的应用程序并不需要预渲染(现在它已经成为我的预渲染器)
  • 当用户inputwww.example.com时,他碰到我需要的nginx代理
    • 代理/adminold.example.com/admin
    • 将所有机器人请求代理给预渲染器
    • 默认代理到new.example.com

为了使事情更简单,我有代表每个应用程序@地点块(但也许这是不相容的,请告诉我)

location @newapp { proxy_pass http://new.example.com:8080; } location @oldapp { proxy_pass http://old.example.com:8080; }

现在,当我的新应用程序正在开发中时,我希望/adminurlredirect到我的旧应用程序。 我在网上find了一个使用try_files和maintenance.html文件的技巧

location /admin { try_files /maintenance.html @oldapp; }

现在事情也变得严重 – 我的新应用程序需要预渲染 – 我的旧应用程序不需要预渲染,并用作当需要元素的后备 – 现在我没有prerenderer应用程序(我将安装/设置prerenderer。后来)所以我使用我的旧应用程序作为bot引擎的预渲染器

 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不喜欢if块中的try_files

你将如何编写nginx conf文件?

我的完整的nginxconfiguration文件看起来像

 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; } 

发生错误是因为在if块内不允许try_files

我会尝试使用map指令来实现后端的select:

 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; } 

使用这两个映射,您将获得一个variables$render ,它将包含oldapp ,当没有指定的规则匹配时,或者当两个用户代理匹配或查询参数包含已定义的string时prerender

我不是100%肯定这个部分,但是你可以使用像这样的variables:

 location / { try_files /maintenance.html @$render; } 

这样你可以避免if语句,这是邪恶的 。