nginx 的 proxy_pass 发出的请求失败,但如果手动完成,请求就会成功

nginx 的 proxy_pass 发出的请求失败,但如果手动完成,请求就会成功

我正在代理位于第二个 nginx 实例(将请求发送到 PHP-FPM)后面的 WP 博客。

如果我从浏览器或命令行(如 HTTPie)发出请求,则请求会成功。例如

$ http http://x.y.z.w/test-page/
HTTP/1.1 200 OK
...

但是,proxy_pass在我的电脑上使用 nginx 实例时返回 404。检查 WP 的博客 nginx 日志后,我看到以下内容:

<my-ip> - - [05/Nov/2019:09:53:37 +0000] "GET /test-page/ HTTP/1.1" 404 196 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"
<my-ip> - - [05/Nov/2019:09:53:43 +0000] "GET /test-page/ HTTP/1.1" 200 21317 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"

一切看起来都一样,但服务器首先返回 404,然后返回 200,这怎么可能呢?肯定有区别。我还检查了 HTTPie 发送的标头。没有什么不寻常的:

GET /test-page/ HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: x.y.z.w
User-Agent: HTTPie/0.9.9

以下是本次测试的最小 nginx 配置:

events {
    worker_connections                 5000;
    multi_accept                       on;
    use                                epoll;
}

http {
    log_format                          timed_combined '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '$request_time';

    access_log                           /var/log/nginx/access.log timed_combined;
    error_log                            /var/log/nginx/error.log warn;

    resolver                             1.1.1.1 8.8.8.8 8.8.4.4 valid=60s;
    resolver_timeout                     15s;

    index                                index.html;

    upstream front-wp {
        server x.y.z.w:80;
    }

    server {
        listen 80;

        location /wp-content/ {
            proxy_pass http://front-wp;
            proxy_http_version 1.1;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        location = /test-page/ {
            proxy_pass http://front-wp;
            proxy_http_version 1.1;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

这个问题确实让我抓狂。

答案1

可能是服务器x.y.z.w正在使用基于名称的虚拟主机,并且两个请求由不同的虚拟主机处理。

URLhttp://x.y.z.w/test-page/设置 Host 标头值x.y.z.w,用于选择其中一个虚拟主机。

通过反向代理的请求将 Host 标头值设置为该值,$host用于选择另一个虚拟主机(当 Host 值未知时可能是默认主机)。

为了确认这一点,请尝试:

proxy_set_header Host "x.y.z.w";

这应该使两个请求足够相似以便由同一个虚拟主机处理。

x.y.z.w如果需要不同的行为,您将需要查看服务器的配置。

相关内容