3

我正在创建一个混合 PHP/Node.js 应用程序。对于 PHP,我使用的是 Yii 框架。在 Node.js 中,我使用 express。

PHP 通过 Nginx 运行。我使用 proxy_pass 指令将任何以 /node 开头的请求集中到运行在端口 3000 上的节点服务器(例如 server.com/node/api 被代理到 server.com:3000/api。)

在大多数情况下,这很好用。但是,我的 Nginx 配置文件中的指令之一确保对不存在的静态文件的请求不会传递给 Yii。相反,会返回一个简单的 404 错误。该指令的原始版本如下所示:

location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar|txt)$ {
    try_files $uri =404;
    #For production servers you can set expires header with a long period
    expires 3M;
}

该指令的问题在于 Node.js 提供了一些静态文件(尤其是 socket.io 客户端)。当浏览器请求 server.com/node/socket.io/socket.io.js 时,上述规则被触发,Nginx 返回 404。

我想要做的是修改规则,以便仅当对静态文件的请求不以 /node/ 开头时才返回 404。我尝试了各种规则组合,但似乎没有一个有效。在查阅了 perl 正则表达式文档之后,我认为这是一个可能有效的文档,但没有:

location ~* (?<!/node/)\.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar|txt)$ {
    try_files $uri =404;
    expires 3M;
}

我认为规则的否定/后视部分(?<!/node/)可以排除以 /node/ 开头的请求,但事实并非如此。相反,对于真正不存在的 js 文件和 socket.io.js(以及从 Node.js 提供的各种其他静态文件)都会触发该规则。所以在这两种情况下我都会得到 404。

我应该如何更改正则表达式,以便仅在请求不以 /node/ 开头时应用规则?

4

3 回答 3

7

如果我没看错你的问题,你说的是不以 . 开头的 /node/路径。这比匹配前面没有的东西要简单得多。这应该这样做:

location ~* ^(?!/node/).*\.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar|txt)$ {

我认为@Pogo 几乎拥有它,但据我所知,它location不包括服务器名称。正则表达式开始锚点,^匹配紧接在.com(在这种情况下)和第一个斜杠之前的位置。因此,^(?!/node/)确保您的路径不以/node/.

于 2012-10-21T09:31:35.847 回答
1

问题是,负面的lookbehind 看起来直接在点的前面。不幸的是,据我所知,只有 .NET 支持可变长度的lookbehinds。解决方法是反转字符串,反转正则表达式并在末尾使用负前瞻(可以是可变长度):

(?!.*/node/)

不幸的是,我现在无法写出完整的正则表达式,因为我正在手机上打字。

于 2012-10-21T06:56:55.323 回答
1

我认为问题可能是因为 javascipt 不完全支持向后看。可以先看开头看看是不是/node/,然后继续。

所以,

.*com(?!/node/).*\.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar|txt)$

可能会帮助你。

于 2012-10-21T06:57:55.357 回答