framework icon indicating copy to clipboard operation
framework copied to clipboard

nginx的伪静态规则应该调整为!-f,否则在某些场景下会出错。

Open augushong opened this issue 3 years ago • 0 comments

官网文档的写法如下: 后面称为:A用法。

location / {
    if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php?s=$1 last; break;
    }
}

实际上使用!-f会更好一些: 后面成为B用法。

location / {
    if (!-f $request_filename) {
        rewrite ^(.*)$ /index.php?s=$1 last; break;
    }
}

!-e判断的是目录或文件是否不存在,不存在时则重写。 !-f判断的是文件是否不存在,不存在时则重写。

以上虽然差别很小,但是实际上却有很大的不同。

当使用A用法时,只有get、head、post方法会进入转发,而其他的方法比如put、patch不会进行重写,这跟定义路由没有任何关系,因为这个链接根本就没有进入重写。没有执行index.php。而且会返回405错误。

此时如果我们想定义一个路由去处理这类的请求,根本不可能,因为nginx没有重写到php上。更重要的是会返回405错误。

Route::rule('/', function (Request $request) {
    Log::debug('进入路由');
    $method = $request->method();
    Log::debug($method);
   。。。。
});

然而一个极其简单的解决方案是,把A用法换成B用法。

换成B方法,就都可以将请求重写到php中。这时定义的路由文件就可以全部匹配到相应的请求。

http还有其他一些扩展请求,比如webdav的PROPFIND,MKCOL等,使用B方法也都会正常表现,此时如果是用A方法,则会返回405错误。

注意,只是请求跟目录时会发生以上情况:

https://servername/

只要带有path就不会:

https://servername/aaa

这就更需要换成B方法,因为同样的请求method,带了path,就能正常重写且不报错,不带path,就会报错,表现严重不一致。

比如使用A方法时,option请求根目录会返回405错误,但option请求带有path的路径(servername/aaa),就是正常的204 。 使用PUT请求也是如此。 但是调整为B方法,则是否带有path,都会表现一致。

augushong avatar May 05 '22 15:05 augushong