nginx - user_agent 上的 proxy_pass

nginx - user_agent 上的 proxy_pass

我有一个 SPA 网站,我需要<meta>为每个子页面加载适当的标签,但从子页面本身来看并不容易,所以我创建了一个单独的地址,Facebook 或 Twitter 机器人可以在那里下载适当的 OpenGraph 值。它看起来像这样:

原始网址http://website.com/contents/1
此 URL 带有 OG 标签的路由http://website.com/og/contents/1

我想proxy_pass为此使用,只考虑特定的User-Agent,但是以下配置不起作用,即没有重定向:

    location /contents {
        resolver 127.0.0.11 ipv6=off valid=5m;

        if ($http_user_agent ~* ("(facebookexternalhit)\/(.*)|(Twitterbot)\/(.*)")) {
            proxy_pass http://$host:8080/open-graph$request_uri;
        }
    }

有谁看到哪里不好吗?

答案1

首先,当你需要在 nginx 配置中使用一些字符串时,你可以使用单引号或双引号,或者根本不使用它们(除非你的字符串包含一些特殊字符,如空格、花括号等)。在你的情况下,nginx 假定你不使用任何引号(因为你的字符串以圆括号开头),因此 nginx 处理的正则表达式字符串("(facebookexternalhit)\/(.*)|(Twitterbot)\/(.*)")包括圆括号和双引号。除非它包含"facebookexternalhit/...""twitterbot/..."子字符串,否则它不会匹配任何用户代理用双引号

其次,您不需要那么多捕获(事实上您根本不需要它们,因为您以后不会使用它们)。这些捕获使 nginx 在将字符串与正则表达式匹配时花费一些额外的资源(这不是您在高负载系统上想要的)。以下块应该按预期工作(请注意,符号不需要/转义,尽管转义它不会破坏正则表达式):

    if ($http_user_agent ~* (facebookexternalhit|twitterbot)/) {
        proxy_pass http://$host:8080/open-graph$request_uri;
    }

然而,这不是一个好的解决方案。最好避开if建筑物除非你只使用ngx_http_rewrite_module块内的指令if。在我们的例子中,nginx 将创建两个配置 - 如果 User-Agent 字符串与正则表达式匹配,则将使用第一个配置,如果不匹配,则将使用第二个配置。我强烈建议不要if在这里使用构造。您可以使用map改为翻译:

map $http_user_agent $og_prefix {
    ~*(facebookexternalhit|twitterbot)/  /open-graph;
}

server {
    ...
    location /contents {
        resolver 127.0.0.11 ipv6=off valid=5m;
        proxy_pass http://$host:8080$og_prefix$request_uri;
    }
    ...
}

如果 User-Agent 字符串与正则表达式匹配,则变量的值$og_prefix将为空字符串。/open-graph

相关内容