在if语句中使用proxy_pass进行奇怪的重定向

时间:2017-10-28 17:01:42

标签: regex apache redirect nginx

我是一个SPA(单页应用程序)网站,请在https://example.com下说明,https://api.example.com下的API

我想为googlebotfacebookexternalhit等特定用户提供服务器呈现的内容。

因此,如果用户转到https://example.com/brandon/things,它将获得SPA服务,但如果bot转到相同的URL,它将获得服务器呈现的页面,其中包含所有正确的元图和开放图标签。

我的服务器呈现的网页具有正确的匹配位于https://api.example.com/ssr/

例如,如果机器人点击https://example.com/brandon/things,它应该从https://api.example.com/ssr/brandon/things

获取内容

我几乎使用nginx proxy_pass if语句到Django应用程序(它返回服务器渲染输出)但不幸的是有一个边缘情况使它表现得很奇怪。

我的实施:

server {
    listen 80;
    server_name example.com; # url of SPA 
    index index.html;

    root /srv/example_spa/public/dist; # directory of SPA index.html


    # $ssr variable that tells if we should use server side rendered page

    set $ssr 0;
    if ($http_user_agent ~* "googlebot|yahoo|bingbot|baiduspider|yandex|yeti|yodaobot|gigabot|ia_archiver|facebookexternalhit|facebot|twitterbot|developers\.google\.com|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator|redditbot") {
        set $ssr 1;
    }


    # location block that serves proxy_pass when the $ssr matches
    # or if the $ssr doesn't match it serves SPA application index.html

    location / {

        if ($ssr = 1) {
            proxy_pass http://127.0.0.1:9505/ssr$uri$is_args$args;
        }

        try_files $uri /index.html;

    }


}

但问题是:

除了一个案例外,一切都很好看。

用户点击https://example.com/brandon/things/并获得SPA index.html - 完美。

用户点击https://example.com/brandon/things并获得SPA index.html - 完美。

Bot点击https://example.com/brandon/things/并获得服务器呈现页面 - 完美。

Bot点击https://example.com/brandon/things(没有附加斜线),他被重定向(301)到https://example.com/ssr/brandon/things - 坏坏了

我已经试着让它工作几个小时而现在没有运气。  你会建议什么?我知道如果在nginx中是邪恶的,但我不知道如何在没有它的情况下使它工作......

感谢任何帮助

2 个答案:

答案 0 :(得分:0)

您需要更改proxy_pass

的重定向
location / {
    proxy_redirect http://127.0.0.1/ssr/ http://$host/ssr/;
    proxy_redirect /ssr/ /;

    if ($ssr = 1) {
        proxy_pass http://127.0.0.1:9505/ssr$uri$is_args$args;
    }

    try_files $uri /index.html;

}

答案 1 :(得分:0)

事实证明这是我的Django应用程序重定向的问题。我以为我有" APPEND_SLASH"选项已禁用,但已启用并在没有斜杠时进行重定向。并且它重定向而不将主机更改为https://api.example.com,但只有URI部分。因此我的困惑。

我实际上找到了两种解决方法。

首先,只有在没有斜线时才使用重写来附加斜杠。

location / {

    if ($ssr = 1) {
        rewrite ^([^.]*[^/])$ $1/ permanent;
        proxy_pass http://127.0.0.1:9505/ssr$uri$is_args$args;
    }

    try_files $uri /index.html;

}

第二次,修改proxy_pass,以便在$ uri部分和服务器端渲染应用程序url config之后始终添加/斜杠,以在最后接受两个斜杠//'。它有点hacky但没有任何副作用,并且可以正常工作。

Nginx配置:

location / {

    if ($ssr = 1) {
        proxy_pass http://127.0.0.1:9505/ssr$uri/$is_args$args;
    }

    try_files $uri /index.html;

}

Django URL正则表达式:

r'^ssr/(?P<username>[\w-]+)/(?P<slug>[\w-]+)(/|//)$'