Nginx 预渲染、重定向、内容协商和 HTTP HEAD 请求

Nginx 预渲染、重定向、内容协商和 HTTP HEAD 请求

我正在运行一个 javascript 应用程序,其中为 Google 机器人等启用了 Prerender.io。

使用 Prerender.io 推荐的配置,任何匹配的用户代理都会重定向到他们的站点并提供预渲染的页面。

需要与一些合作伙伴服务合作,这些服务将尝试连接到我们的 javascript 页面,并发出 HTTP HEAD 请求以获取有关页面的信息,或使用内容协商来请求一些 JSON。这应该只发生在特定的 URL 上,特别是那些有记录 ID 的 URL,例如“/example.xyz890”。

这样做的一个问题是,重定向到 Prerender.io 似乎发生在检查与 URL 匹配的任何规则之前。有人能想到一种修改此 Nginx 配置的方法,以便我可以在任何用户代理匹配和后续重定向发生之前检查特定的 URL?

我在下面放了我们的配置的删节版,其中在端口 443 部分有一个位置块。

server {
  listen 80;
  server_name example.org;
  return 301 https://$server_name$request_uri;
}


map $http_user_agent $prerender_ua {
    default       0;
    "~*Prerender" 0;

    "~*googlebot"                               1;
    "~*yahoo!\ slurp"                           1;
    # Long list of user agents removed for brevity...
}


map $args $prerender_args {
    default $prerender_ua;
    "~(^|&)_escaped_fragment_=" 1;
}


map $http_x_prerender $x_prerender {
    default $prerender_args;
    "1"     0;
}

map $uri $prerender {
    default $x_prerender;
    "~*\.(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)" 0;
}

server {
    listen 443 ssl http2;
    server_name example.org;

    ssl_certificate /etc/ssl/example.org/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.org/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;


    # This is never reached if a user agent matches those listed for prerenderio. 
    location ~* "/example-([A-Za-z0-9]{4,6})$" {
      add_header Link: "https://example.org/mysite-$1; rel='cite-as'";

      # Detecting and responding (with a redirect) to a request for e.g. JSON would be useful here. 
      # JSON could be sent from api.example.org/example-$1, for example. 
    }

    # Logs cut for brevity...

    location /prerenderio {
        if ($prerender = 0) {
            return 404;
        }

        proxy_set_header X-Prerender-Token "abc123";

        proxy_hide_header Cache-Control;
        add_header Cache-Control "private,max-age=600,must-revalidate";

        #resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
        resolver 8.8.8.8 8.8.4.4;
        set $prerender_host "service.prerender.io";
        proxy_pass https://$prerender_host;
        rewrite .* /$scheme://$host$request_uri break;
    }
}

答案1

我认为这可以解决问题。这里的 URL 中的记录 ID 只是一个整数:

location ~* "/[0-9]+$" {
        proxy_http_version 1.1;
        add_header Link "https://www.example.org/$1; rel='cite-as'";
        if ($http_accept ~* 'application/json') {
            rewrite ^/([0-9]+) /content_negotiation/json/$1 break; 
            proxy_pass https://api.example.org;
        }
        root /var/www/example-client/dist;
        try_files $uri $uri/ /index.html;
    }

需要 proxy_http_version 来防止 curl 抱怨连接未关闭。

相关内容