尝试使用 Nginx try_files 来模拟 Apache MultiViews

Sam*_*gen 2 rewrite nginx

我想要一个http://example.com/foobar返回的请求http://example.com/foobar.jpg。(或 .gif、.html、.whatever)

这与 Apache MultiViews 无关,在 Nginx 中似乎同样容易。这个问题似乎暗示它会像try_files $uri $uri/ index.php;在 location 块中一样简单,但这不起作用。

try_files $uri $uri/ =404;不起作用,try_files $uri =404;或者try_files $uri.* =404;在我的location / {块和匹配图像的正则表达式之间移动它也不起作用。

至关重要的是,try_files $uri.jpg =404; 确实有效,但仅适用于 .jpg 文件,如果我在一个位置块中使用多个 try_files 规则,则会引发配置错误!

当前server {区块:

server {
        listen   80;
        server_name     example.org www.example.org;
        access_log  /var/log/nginx/vhosts.access.log;
        root   /srv/www/vhosts/example;
        location / {
                root   /srv/www/vhosts/example;
        }

        location ~* \.(?:ico|css|js|gif|jpe?g|es|png)$ {
                expires max;
                add_header Cache-Control public;
                try_files $uri =404;
        }
}
Run Code Online (Sandbox Code Playgroud)

Nginx 版本是 1.1.14。

cyb*_*x86 5

您可以通过将各种文件名传递给try_files.

Nginx 的try_files指令完全符合名称所暗示的意思——它按照指定的顺序尝试文件,如果没有找到,将移动到下一个文件。通常,最后一个条目是保证工作的回退 - 命名的位置块或错误页面。

try_files:$uri和的常见参数$uri/实际上是传递给 nginx 的路径 - 带有和不带有尾部斜杠。

所以,如果你去 example.com/path/to/myfile

$uri = /path/to/myfile
$uri/ = /path/to/myfile/
Run Code Online (Sandbox Code Playgroud)

使用该try_files $uri $uri/指令,nginx 将准确地尝试传递的内容 ( $uri) - 如果该文件存在,则为其提供服务,否则将尝试找到匹配的目录 ( $uri/) 并提供服务(使用您指定的任何索引)。

由于您尝试提供的文件实际上与 中的路径不匹配$uri,因此您需要附加扩展名才能$uri使其工作:

$uri.jpg将匹配(来自上面的示例)myfile.jpg-因此,为什么在您使用它时只有 JPEG 可以工作。

由于您可以指定多个文件进行尝试try_files,因此拥有多个try_files指令并没有真正意义 - 这就是不允许的原因。

因此,以最简单的形式,只需按照您希望尝试的顺序列出您想要的文件(例如):

try_files $uri.jpg $uri.gif $uri.png $uri.css $uri.js $uri/ =404
Run Code Online (Sandbox Code Playgroud)

在这种情况下,第二个位置块很有趣。通常,nginx 只会处理一个位置块 - 最匹配的那个。但是,在rewrite ... last处理的情况下将重新启动并检查所有可用的位置块。这基本上try_files相当于 - 检查是否存在和rewrite ... last,关键区别在于没有传递的参数,try_files除非明确添加(例如 with $uri?$args),否则会被剥离。