使用 nginx 代理为 googlebot 等机器人提供静态 S3 到不同的存储桶

Using nginx proxy to serve static S3 to a different bucket for bots like googlebot

使用 nginx 将 superduper.io 的子域代理到 S3 存储桶中的特定文件夹。该存储桶为每个包含静态 HTML 网站的子域都有一个文件夹。

现在我想将机器人重定向到不同的 S3 存储桶。我需要在我的 nginx.conf 文件中添加什么?

worker_processes auto;
# include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {
    server {
        listen 80;
        server_name *.superduper.io;
        access_log /var/log/nginx/superduper.access.log;
        error_log /var/log/nginx/superduper.error.log;

        location / {
            resolver 8.8.8.8;
            set $bucket "https://superduper-spa.s3.us-east-1.amazonaws.com:443";
            rewrite ^([^.]*[^/])$ / permanent;

            # matches: subdomain.superduper.io
            if ($host ~ ^([^.]*)\.superduper\.io) {
                set $subdomain ;
                proxy_pass https://$bucket/${subdomain}${uri};
            }

            proxy_intercept_errors on;
            proxy_redirect off;
            proxy_set_header Host $bucket;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_hide_header x-amz-id-2;
            proxy_hide_header x-amz-request-id;
        }
    }

    # include /etc/nginx/conf.d/*.conf;
    # include /etc/nginx/sites-enabled/*;
}

由于 nginx 不支持 else 语句,也不支持具有多个条件的 if,因此编写依赖于多个变量的某些配置可能会变得棘手。

对于您的用例,潜在解决方案有两个改进,可以一起使用或分开使用:

  • 您可能希望将现有的 if 与围绕 $host 的正则表达式转换为 命名捕获 server_name 根据 http://nginx.org/r/server_name。这样,您就可以自由地使用围绕 $http_user_agent 匹配机器人所需的任何转换,例如,通过使用更像是实际条件的 if 语句,而不仅仅是捕获子域。

    -server_name *.example.su;
    -if ($host ~ ^([^.]*)\.example\.su$) {
    -       set $subdomain 
    -}
    +server_name ~^(p<subdomain>[^.]*)\.example\.su$;
    
  • 您可能想使用 http://nginx.org/r/map。它允许将任何输入映射到输出。您可以组合 $host$http_user_agent 的匹配项来进行转换。

    map $http_host/$http_user_agent $bucket {
        "~^(p<subdomain>[^.]*)\.example\.su.*bot.*$"    $bucketPrefix/$subdomain/bot;
        "~^(p<subdomain>[^.]*)\.example\.su.*$" $bucketPrefix/$subdomain;
        default             $bucketPrefix;
    }
    server {
        …
            proxy_pass $bucket$uri;
    }
    

替代解决方案是在 S3 前面使用 Cloudfront,然后使用 Lamdbda at edge 函数将特定 user-agents 重定向到不同的存储桶,而无需接触 nginx。