Назад | Перейти на главную страницу

nginx - proxy_pass на user_agent

У меня есть СПА-сайт, на котором мне нужно загрузить соответствующие <meta> Теги для каждой подстраницы, но это не так просто из самих подстраниц, поэтому я сделал отдельный адрес, по которому боты Facebook или Twitter могут загружать соответствующие значения OpenGraph. Выглядит это так:

Исходный URL: http://website.com/contents/1
Маршрут с тегами OG для этого URL: 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;
        }
    }

Кто-нибудь видит, где плохо?

Во-первых, когда вам нужна какая-то строка в вашей конфигурации 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;
    }
    ...
}

Ценность $og_prefix переменная будет /open-graph если строка User-Agent соответствует регулярному выражению, или пустая строка в противном случае.