综合百科

Nginx 405 not allowed 异常要怎么办处理

Nginx 405 not allowed 异常要怎么办处理,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

今天遇到一个问题,当配置好的前端工程放到服务器上使用nginx启动的时候,报了405 Not allowed 异常,在网上百度了一下,说是这个问题出现的原因是因为使用了post 请求去获取静态资源,我觉得很奇怪,请求的接口都是业务接口,并不存在请求静态资源,是不是nginx对静态资源理解有什么误会,或者说我对静态资源理解不对,抱着这个想法,我把静态资源的概念又梳理了一遍:

静态资源:指的就是在html中的js/css/jpg/png/xxx.json...等等这些在前端工程中需要提前配置或者编译之后的文件,而且这些文件并不会时刻变化或者说变化周期比较长

解决尝试

好的,接下来我就试着根据百度出来的解决办法都尝试了一遍,毕竟网上这么多提出解决办法的,总有一个能解决吧,于是就开始尝试了各种网友的解决办法:

  1. location中配置error_page,这个解决问题的思路是将post请求转换成get请求,配置信息如下:

server{listen80;server_name域名;location/{root/www/文件目录;indexindex.htmlindex.htmindex.php;error_page405=200http://$host$request_uri;}}

这样写是有问题的,有网友提到这样写只适用于post请求中不带参数的请求,带参数的post请求如果使用这种方式可能会导致参数体丢失

2. 修改nginx下src/http/modules/ngx_http_static_module.c文件,如下:

if(r->method&NGX_HTTP_POST){returnNGX_HTTP_NOT_ALLOWED;}

这个办法是修改nginx的源码,将这一段代码注释掉,重新编译,注意,注释的时候需要使用 /* */ 的方式,而不是 # 这个符号,不然会报错,参考这个

3. 修改错误界面指向(网上多流传这种方式,但是没有改变请求方法,所以行不通,所以采用以下方法),代码如下:

upstreamstatic_backend{serverlocalhost:80;}server{listen80;error_page405=200@405;location@405{root/srv/http;proxy_methodGET;proxy_passhttp://static_backend;}}

这个处理的思路是将405的错误信息重新指向一个命名为@405location地址,同时修改请求方式为get方法,这个方法同上面的第一个方法是一样的。这个location将请求重新发送给proxy_pass中定义的static_backendupstream原本是用来配置负载均衡地址的,这里直接给了一个后台访问地址,思路没问题

不过,很不幸的是,上面这些方法中我试过了第一个和第三个,对我没有效果,第二个我就不去试了,我觉得nginx这样的设置肯定是有他的道理的,即使通过修改源码暂时达到了预期的效果,那这样也会带来隐患,难道以后就不升级nginx了吗,是吧,所以我觉得修改源码是最不靠谱的办法。

既然这几个方法都没有效果,那就看看后台服务的日志有没有收到请求,结果发现后台服务启动之后根本就没有收到Nginx 的任何请求转发,也就是说所有的请求(包括get)都没有到达后台,此时我就开始怀疑是location配置的问题,为什么这么说呢,因为如果是普通的405 not allowed异常情况,至少get请求是没有问题的,但是在查看控制台以及后台服务后发现,后台没有接收到请求,而浏览器的控制台中-network一栏,get请求的respone是一个静态页面,也并不是预想中的json数据,如下:

而在Headers一栏显示请求是OK的,如下:

根据这个情况我更加确定,这个问题并不是它表现出来的 405 not allowed,很有可能是由于 location配置异常导致了 405 not allowed,顺着这个思路我又复习了location的配置,我原来的location 配置如下:

location=/demo{#rewrite^.+demo/?(.*)$/$1break;proxy_passhttp://localhost:19998;proxy_set_headerHost$host:$proxy_port;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;proxy_set_headerX-NginX-Proxytrue;proxy_read_timeout90;proxy_buffer_size4k;proxy_buffers432k;proxy_busy_buffers_size64k;proxy_temp_file_write_size64k;}location/{root/home/jenkins/workspace/demo-2.0/dist;try_files$uri$uri//index.html;proxy_redirecthttp://https://;proxy_set_headerUpgrade$http_upgrade;proxy_set_headerConnection"upgrade";}

这是一个严格匹配模式,在location中有3中匹配模式,参考这个,分别是:

  • location = patt {} [精准匹配]

  • location patt{} [普通匹配]

  • location ~ patt{} [正则匹配]

其中精准匹配的优先级最高 --> 普通匹配 --> 正则匹配。

问题解决

我将location = /demo {}修改成了location /demo {}就解决了问题,为什么呢?

个人理解,精准匹配是需要指定到具体某一个访问资源的,比如:location = /demo/index.html,应该这样写才对,我的post请求中请求的url地址是一个很长串的地址,比如:localhost:19999/demo/user/query 这种,所以其实根本就没有匹配到 /demo,而是匹配到了最下面的 location / {}这里,所以请求全都被发送到了主页面上,导致nginx判断所有的请求都是在请求一个index.html,这违反了nginx的设计原则,即:不允许静态文件响应POST请求,所以才出现了***404 not allowed*** 的异常。

看完上述内容,你们掌握Nginx 405 not allowed 异常要怎么办处理的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!