除一条路径之外,将所有 URL 重定向到其他(外部)站点?

除一条路径之外,将所有 URL 重定向到其他(外部)站点?

我有一个正在运行的网站http://www.example.com(使用 PHP-FPM),我想将其所有传入流量重定向到另一个网站(ttps://www.other-example.com/foo.html)上的 URL,除了一个特定路径(/api)。

下面是我尝试过的 Nginx 配置(将 PHP 处理内容放在专用的locationfor/apireturn 301on 中location /):

upstream php {
    server unix:/var/run/php/php7.4-fpm.sock;
}

server {
    listen 80;
    listen [::]:80;

    server_name www.example.com;

    root /var/www/www.example.com;
    index index.php;

    location  ~ ^/api(?:/(.*))?$ {
        #return 418;
        try_files $uri $uri/ /index.php$is_args$args;
    
        location ~ \.php$ {
            #include snippets/fastcgi-php.conf;

            # regex to split $uri to $fastcgi_script_name and $fastcgi_path
            fastcgi_split_path_info ^(.+?\.php)(/.*)$;

            # Check that the PHP script exists before passing it
            try_files $fastcgi_script_name =404;

            # Bypass the fact that try_files resets $fastcgi_path_info
            # see: http://trac.nginx.org/nginx/ticket/321
            set $path_info $fastcgi_path_info;
            fastcgi_param PATH_INFO $path_info;

            fastcgi_index index.php;
            include fastcgi.conf;
            include fastcgi_params;

            fastcgi_pass php;
        }
    }

    location / {
        return 301 https://www.other-example.com/foo.html;
    }
}

但是我的所有请求(http://www.example.comhttp://www.example.com/foohttp://www.example.com/api)都得到HTTP/1.1 301 Moved PermanentlyLocation: https://www.other-example.com/foo.html

我知道这些location ~ ^/api(?:/(.*))?$工作原理,因为如果我取消注释,return 418;我会得到 418 个http://www.example.com/api请求响应,但其他请求则会得到 301 个响应。

答案1

在您的情况下,nginx 处理如下:

  1. 请求/api/test_endpoint匹配该location ~ ^/api(?:/(.*))?$块。
  2. 在 中try_files,它匹配/index.php$is_args$args部分。由于它是最后一部分,因此会触发内部重定向。
  3. nginx 使用 uri 重新启动处理/index.php。这将匹配location /触发重定向的块。

解决该问题的一个解决方案是以下配置:

location  ~ ^/api(?:/(.*))?$ {
    #return 418;
    try_files $uri $uri/ /index.php$is_args$args;
}

location / {
    return 301 https://www.other-example.com/foo.html;
}

location = /index.php {
    internal;
    #include snippets/fastcgi-php.conf;

    # regex to split $uri to $fastcgi_script_name and $fastcgi_path
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;

    # Check that the PHP script exists before passing it
    try_files $fastcgi_script_name =404;

    # Bypass the fact that try_files resets $fastcgi_path_info
    # see: http://trac.nginx.org/nginx/ticket/321
    set $path_info $fastcgi_path_info;
    fastcgi_param PATH_INFO $path_info;

    fastcgi_index index.php;
    include fastcgi.conf;
    include fastcgi_params;

    fastcgi_pass php;
}

index.php通过此配置,nginx在请求处理的第 3 步中找到匹配项。internal关键字阻止外部请求/index.php匹配此块。外部请求将由块/index.php提供服务。location /

相关内容