如何使具有多个后备功能的try_files在Nginx中工作?

时间:2019-01-30 21:43:09

标签: django nginx prerender

我有nginx作为两个应用程序服务器的代理运行:daphnegunicorn

我的webApp是AngularJs单页应用程序。因此,我需要使用prerender.io来帮助机器人抓取网站。

我的nginx文件:

upstream ex_server{
 server unix:/home/webapps/ex/run/gunicorn.sock fail_timeout=0;
}

upstream channels-backend {
    server 0.0.0.0:8001;
}

server {
    server_name example.com;
    listen 80; 
        rewrite ^ https://$http_host$request_uri permanent;
}

server {
    server_name example.com;

    listen 443 ssl;
    ssl_certificate /etc/ssl/_cert_chain.crt;
    ssl_certificate_key /etc/ssl/_in.key; 

    root /usr/share/nginx/html;

    server_name _;

    location / {
            try_files /$uri @prerender;
            #try_files /$uri @prerender @proxy_to_main_app; <= I wanted this
    }

    location @proxy_to_main_app {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;  # <-
            proxy_set_header Host $http_host;
            proxy_redirect off;
            #proxy_buffering off;

            try_files $uri @proxy_to_daphne_app;

        if (!-f $request_filename) {
            proxy_pass http://ex_server;
            break;
        }
    }

location @proxy_to_daphne_app {
    proxy_pass http://channels-backend;
    proxy_set_header X-Forwarded-Proto https;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    proxy_redirect off;
    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 X-Forwarded-Host $server_name;
}

location @prerender {
    proxy_set_header X-Prerender-Token RMVQxJkVVugDjcPgHakN;
    set $prerender 0;
    if ($http_user_agent ~* "googlebot|bingbot|yandex|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;
    }

    resolver 8.8.8.8;

    if ($prerender = 1) {
        set $prerender "service.prerender.io";
        rewrite .* /$scheme://$host$request_uri? break;
        proxy_pass http://$prerender;
    }
    if ($prerender = 0) { 
        # here is the problem. when $prerender=0 means it isn't the crawler requesting a rendered page but an actual user. So, we need to show path to our webApp as usual.
    }
}

    }

您可以看到,我有三个后备@prerender@proxy_to_main_app@proxy_to_daphne_app

现在@prerender工作正常。但是if($prerender=0),我需要尝试@proxy_to_main_app,即

if($prerender=0){
    try_files @proxy_to_main_app
}

但这不起作用。 nginx不允许try_files位于if中。

请提供解决方法。我浏览了所有其他帖子。但是没有帮助。

1 个答案:

答案 0 :(得分:0)

try_files中只能有一个@位置,因此您可能希望尝试合并这些位置。并且try_files的$ uri部分实际上是否与此文件系统上的任何文件匹配,还是仅代理请求?这样的东西行吗?

upstream ex_server{
 server unix:/home/webapps/ex/run/gunicorn.sock fail_timeout=0;
}

upstream channels-backend {
    server 0.0.0.0:8001;
}

server {
    server_name example.com;
    listen 80; 
        rewrite ^ https://$http_host$request_uri permanent;
}

server {
    server_name example.com;

    listen 443 ssl;
    ssl_certificate /etc/ssl/_cert_chain.crt;
    ssl_certificate_key /etc/ssl/_in.key; 

    root /usr/share/nginx/html;

    server_name _;

    location / {
            proxy_set_header X-Prerender-Token YOUR_TOKEN;
            set $prerender 0;
            if ($http_user_agent ~* "googlebot|bingbot|yandex|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;
            }

            resolver 8.8.8.8;

            if ($prerender = 1) {
                set $prerender "service.prerender.io";
                rewrite .* /$scheme://$host$request_uri? break;
                proxy_pass http://$prerender;
            }

            try_files /$uri @proxy_to_main_app;
    }

    location @proxy_to_main_app {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;  # <-
            proxy_set_header Host $http_host;
            proxy_redirect off;
            #proxy_buffering off;

            try_files $uri @proxy_to_daphne_app;

        if (!-f $request_filename) {
            proxy_pass http://ex_server;
            break;
        }
    }

    location @proxy_to_daphne_app {
        proxy_pass http://channels-backend;
        proxy_set_header X-Forwarded-Proto https;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_redirect off;
        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 X-Forwarded-Host $server_name;
    }

}