nginx try_files、proxy_pass和上游

2022-08-30 22:21:18

我正在为PHP应用程序构建一个dockerized测试“平台” - 特别是(目前)用于WordPress。我正在使用PHPFarm在不同的端口上提供不同版本的PHP。在前面使用nginx,我已经让它的大部分工作。(https://github.com/richardtape/testit 是主回购)

我现在面临的最大问题是让WordPress的“相当永久链接”发挥作用。在标准的nginx设置中,它只是一个类似的东西

location / {
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php?$args;
}

但是,为了能够从主机获得漂亮的URL,并且为了有一个代码库,我使用以下方法:

server {
    listen 80;
    index index.php index.html index.htm;
    server_name 52.spaces.dev;

    location / {

        proxy_pass http://phpfarm_52;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
    root /var/www;
}

upstream phpfarm_52{
    server phpfarm:8052;
}

就目前而言,这是有效的。(PHP 5.3、5.4、5.5、5.6 和 7 还有 5 条类似的规则)主页加载到来自主机的每个不同server_names(如果您在每个服务器上输出PHP版本,您可以看到您正在获得不同的PHP版本)。

但是,当我切换到“内部”网址(或任何非根,即 http://52.spaces.dev/about/)时,我得到一个404。我尝试过类似

location / {
    try_files $uri $uri/ /index.php?$args
}

location ~ \.php$ {
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
}

我得到一个重定向循环,取决于我尝试过的几种不同方式,它要么只是一系列301重定向,页面从未加载,要么是错误,例如

nginx_1      | 2016/04/08 20:31:29 [error] 5#5: *4 rewrite or internal redirection cycle while processing "/index.php", client: 192.168.99.1, server: 52.spaces.dev, request: "GET /favicon.ico HTTP/1.1", host: "52.spaces.dev", referrer: "http://52.spaces.dev/"

我被卡住了。我对nginx配置也很陌生(这可能是显而易见的),所以我很可能正在做一些完全错误和/或愚蠢的事情。有什么建议吗?


答案 1

您在问题中遇到的重定向循环问题是,基本上每个请求(即使是静态文件)都会尝试通过索引进行路由.php$args块。

我在这里看到了2种可能的解决方案。首先,如果您愿意使用单个nginx实例实现nginx设置,请查看此线程:NGINX try_files具有多个命名位置,此博客文章 http://linuxplayer.org/2013/06/nginx-try-files-on-multiple-named-location-or-server

需要做的是,您需要首先测试资源是否按原样存在于上游(即不返回404)。如果是这样,那么你就按原样服务它。如果没有,那么您将调用重写块,该块尝试将其作为参数来索引.php。所以你最终会得到这样的东西(抱歉,我真的没有机会测试这个,但希望它能给出一个想法):

location / {
    try_files $uri $uri/ @phpproxy;
}

location @phpproxy {
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @rewrite_proxy;
}

location @rewrite_proxy {
    rewrite ^/(.*)$ /index.php?$1 break;
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
}

第二种解决方案(我个人更喜欢)是用自己的nginx来引导每个上游。然后,前面的顶级nginx将具有更干净的结构,具有简单的proxy_pass(+也许是一些静态内容),仅此而已。它还将减少请求往返,因为您不需要解决来自上游的404。


答案 2

推荐