这是我学习http
的详细踩坑经历,只为伯君一笑:
我希望用axios
来发起一个POST
请求,但是老是报错 status code: 405 Method Not Allowed
。但是奇怪的是GET
就可以。
我反复调试各种参数,
是不是url
不对,相对路径换成绝对路径?
是不是请求头不对,尝试各种content-type
?
我甚至用Jquery
的ajax
, 以及原生xhr
都尝试了一遍还是没有用,一样的问题。
既然客户端不对,那是不是服务端有问题?
是不是windows PC 用来做服务端有什么限制?
于是我百度,把IIS又捣鼓了下,还是没用。
网上还有一些没节操的人说, POST
不行啊,但是就用GET
问题就解决啦,我特么。。。
就这样一天半,就过去了,毫无进展。
我后来想到,既然客户端,服务端都不行,是不是我的PC有问题?毕竟公司的PC为了安全,有各种限制。于是晚上回家用自己的PC,我居然又可以了。。。
于是我把矛头直接指向了公司的PC。 公司的安全设置会做到如此地步吗,可以不让大家发起POST
请求?我将信将疑。
我还是不放弃,因为我觉得我还没有找到真正的原因。
因为我的这个项目里面用到了一个游戏服务器框架,用的是websocket
协议,然后attach了express
。
于是我就还是用公司的PC,重新写了一个简单的小demo,就又可以了。。。
所以这不是公司PC的锅,是我用的游戏服务器框架有这方面的限制?
我甚至准备去github
以及论坛里面开骂了。。。
还是先冷静一下,还有什么我没有想到?
继续排除。
于是我在原项目里面,注释掉所有和gameServer
相关的代码, 然后仅仅在项目里面写得和成功的demo
类似的代码,结果还是不行。 这说明不是gameServer
的锅,好吧,我先放gameServer
的作者一马。
这时候我观察到一个现象。如果我直接在html
的script
标签中写ajax
请求,是管用的。但是如果进行标签引用
<script src="./client.js"></script>
则不灵了。
服务端代码是这样的。
app.get('/chat', (req, res) =>{
res.sendFile(path.join(__dirname, 'client', 'client.html'));
});
client 目录结构
我在想,服务器吧client.html
发送到客户端,没有带上client.js
所以就无法发起ajax
请求了,那怎样才能既带上client.js
,不需要吧js
直接写在html
的script
标签里, 也可行呢?
网上查了下,哦,只要加这句话
app.use("/", express.static(path.join(__dirname, "client")));
这就表示服务端把这些静态资源都加载了。 你就不会在res.sendFile
的时候无法引用client.js
了。
其实这句话我以前早就放上去了,除了这句,还有另外一句是一起出现的。只是当时在调试的时候都一起注释掉了。
app.use("/", serveIndex(path.join(__dirname, "client"), { icons: true })); //还有这句
app.use("/", express.static(path.join(__dirname, "client")));
这里的serveIndex
是当时游戏框架demo默认加上去的。 这可以让你把目标文件夹的东西都搞成一个静态服务器,然后可以再主页中点击访问各个文件。
于是我把serveIndex
这句注释掉,只留下了 express.static
这句,居然成功的发起post
请求!
所以最后的root cause
终于找到了,不是ajax
设置的锅,不是PC的锅,也不是gameServer
作者的锅,是静态服务器的锅!!!
结论:对于静态服务器中的资源,只能GET
不能POST
当然也不能 PUT
, DELETE
。
结论:对于静态服务器中的资源,只能GET
不能POST
当然也不能 PUT
, DELETE
。
结论:对于静态服务器中的资源,只能GET
不能POST
当然也不能 PUT
, DELETE
。
重要的问题说三遍。
可能对于一些老手,看到这个非常可笑,这啥问题,居然用了这么多笨办法,以及花了两天时间才搞定。
但是作为一个业余选手,基本上就把我折腾够呛了。
这时候我突然想起了两句名人名言。
刘润: 你的顿悟,也许只是别人的基本功(业余对专业而言)
福尔摩斯:排除一切不可能的,剩下的即使再不可能,那也是真相。