如何直接使用NGINX服务所有现有的静态文件,但将其余的代理到后端服务器。


87
location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    if (-f $request_filename) {
        access_log off;
        expires 30d;
        break;
        }

    if (!-f $request_filename) {
        proxy_pass http://127.0.0.1:8080; # backend server listening
        break;
        }
    }

上面的代码将直接使用Nginx服务所有现有文件(例如Nginx仅显示PHP源代码),否则将请求转发给Apache。我需要从规则中排除* .php文件,以便将对* .php的请求也传递给Apache并进行处理。

我希望Nginx处理所有静态文件,让Apache处理所有动态文件。

编辑:有白名单方法,但它不是很优雅,请参阅所有这些扩展名,我不希望这样。

location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
    access_log off;
    expires 30d;
    }
location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
    }

编辑2:在较新版本的Nginx上,try_files改用http://wiki.nginx.org/HttpCoreModule#try_files


只是为了澄清一下:上面的代码将为静态文件(如果磁盘上存在)提供服务,如果该文件不存在,则将请求传递给Apache。由于我的应用程序中的所有URL都使用mod_rewrite(或路由),并且实际上并不存在于磁盘上,因此大多数情况下这是可行的。只有直接访问* .php文件名是例外,需要由Apache解析。
fmalina

Answers:


152

使用try_files和命名的位置块('@apachesite')。这将删除不必要的正则表达式匹配和if块。更高效。

location / {
    root /path/to/root/of/static/files;
    try_files $uri $uri/ @apachesite;

    expires max;
    access_log off;
}

location @apachesite {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

更新:此配置的假设是在下不存在任何php脚本/path/to/root/of/static/files。这在大多数现代php框架中都很常见。如果您的旧版php项目在同一文件夹中混合了php脚本和静态文件,则可能必须将要nginx服务的所有文件类型列入白名单。


我使用的是wordpress,所以我应该将上传文件夹放在nginx服务器上吗?
Chameron

7
这个解决方案的我的问题:nginx不使用其他位置(代理),而是尝试显示目录​​列表。因为目录列表未激活,所以它抛出403。 编辑:好的,如果您删除$uri/则可以。
ChristophLSA

1
这会将/ example代理到apache,但允许/example.php下载。
特伦斯·约翰逊

1
@TerenceJohnson将您的php文件放在静态文件夹下并不安全。请注意,我已设定root /path/to/root/of/*static*/files;。php文件应放在不同的文件夹中,不能直接从Internet访问。
传马

2
我知道事情就是这样,但是如果有人将Nginx放在所有通用的PHP应用程序的前面,这些应用程序的所有内容都位于网络根目录下并且依赖于.htaccess文件,则不应复制和粘贴您的配置。
特伦斯·约翰逊

18

试试这个:

location / {
    root /path/to/root;
    expires 30d;
    access_log off;
}

location ~* ^.*\.php$ {
    if (!-f $request_filename) {
        return 404;
    }
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

希望它能工作。正则表达式比普通字符串具有更高的优先级,因此.php,如果仅.php存在相应的文件,则所有以结尾的请求都应转发给Apache 。其余的将作为静态文件处理。这里是评估位置的实际算法。


6

如果使用mod_rewrite隐藏脚本的扩展名,或者只喜欢以/结尾的漂亮URL,则可能需要从另一个方向进行处理。告诉nginx让具有非静态扩展名的任何内容进入Apache。例如:

location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$
{
    root   /path/to/static-content;
}

location ~* ^!.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$ {
    if (!-f $request_filename) {
        return 404;
    }
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

我在以下网址找到了该代码段的第一部分:http : //code.google.com/p/scalr/wiki/NginxStatic


尽管我仍然遇到缩小文件的错误(例如site.min.css和main.min.js等),但效果很好。我将如何在正则表达式中捕获那些?@lo_fye
Garth
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.