【问题标题】:Modifying an Nginx regular expression so that it is applied only in some cases修改 Nginx 正则表达式,使其仅在某些情况下应用
【发布时间】:2012-10-11 07:44:03
【问题描述】:

我正在创建一个混合 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;
}

这个指令的问题是一些静态文件(特别是 socket.io 客户端)由 Node.js 提供服务。当浏览器请求 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;
}

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

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

【问题讨论】:

    标签: php regex node.js nginx


    【解决方案1】:

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

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

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

    【讨论】:

    • 做到了,艾伦!哇!你的区别是正确的,如果我自己早点掌握它,我会为自己节省很多时间。优秀。谢谢! (您的正则表达式还具有简单得多的优点,而且不像我在回复 m.buettner 时所编造的那样丑陋。)
    【解决方案2】:

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

    所以,

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

    可能会对你有所帮助。

    【讨论】:

    • 其实JS根本不支持lookbehind。但我认为你的正则表达式几乎是正确的。详情见我的回答。
    【解决方案3】:

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

    (?!.*/node/)
    

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

    【讨论】:

    • 这是我最终想出的:(?!(?:(?!\.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar|txt)).)*node).*?\.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar|txt) 似乎有效。这也是我见过的最可怕的正则表达式 :-)
    猜你喜欢
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    • 1970-01-01
    • 2018-04-09
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    相关资源
    最近更新 更多