无知

62885633_p0

令人蛋疼的问题

前些天看到一个比较有趣的包,实现了一个命令行工具。其中涉及到数据网络请求部分是用 request 实现的。
其中的实现方式还是用了传统 cb ,倒不是说不好,只是我一时起兴想要用 promise 风格的实现来重写一遍。
结果用 promise 实现逻辑倒不是难事,反而是其中一个我没有注意的细节害我卡带许久。
于是写一篇博客记录一下

问题

说问题以前先说说出现问题的逻辑吧。
那段代码简单来说就是接受一个用户信息,发起一个登录请求,请求成功后,
会返回一个 302 跳转逻辑,并在 header 中带上 token 信息。逻辑非常简单。

为了方便使用 promise ,我选择用自带 promise 的 http 请求库 axios 替代 request,当然 request 也是有 promise 实现的。
不过我以为我更熟悉 axios 而已。结果问题就出在这里了。

将请求逻辑用 axios 实现以后,却发现无论如果都得不到对应的 302 返回结果。自然也拿不到 token 。
有经验的人应该从描述中也能看到问题所在了,可惜我就没有,所以请允许我细细道来。

过程

请求结构不一致?

一开始,我以为是请求的 header 或是请求体不对。请求体部分很快就确认了,毕竟也就只是账号密码而已。
于是我自然把目光放在了 header ,我首先断点观察了 返回结果中请求部分的 header ,然后发现相比之下,axios 的 header 多了 Accept ,User-Agent 字段。
却少了标记请求提的 content-type 字段(要求的字段是 application/x-www-form-urlencoded),以至于我在想是不是 axios 并没有以正确的 content-type 传递数据,这里就是第一个坑。

axios post 请求会自动处理 content-type 却并不会显示 content-type 出来,这让我难以理解。
以至于我一直以为没有正确设置 content-type ,直到我通过代理抓取到了发出去的包,才确认了实际上是有 content-type 。

接着我把目光放在了 多出来的两个字段,按道理 user-agent 跟 accept 应该都不会影响才对啊。
不过我先是将 user-agent 设置为 chrome 的 user-agent ,结果并没有卵用,同样的 accept
字段也是。看来不是特定的字段值有问题,那么是不是单纯多了这两个字段的问题?

这里就是第二个坑,或许也不算坑,如果你单单是配置 axios 请求的 opts 的话,是没法去除这两个字段的,因为他们都是 axios 默认添加的。
而且添加的时机,在 transformRequest 函数执行以后,所以在 opts 中设定了 transformRequest 去修改 header 也是不行的。
需要额外再 axios 的拦截器中 axios.interceptors.request.use 添加方法去修改才行,不过在还只是可以去除 accept 而已。
真正要连 user-agent 也去除掉,只能改源码…… 是有点蛋疼。

axios 提供了默认值,却不提供不需要这些字段的方法,感觉体贴过头了。

折腾完这些,我最终解决的请求不一致的问题,结果是,并没有什么用,问题不在请求的结构的问题上。
好了,问题到现在也还么解决。我依然拿不到正确的返回,真是丢人了。
真正的问题所在是下面这一点

重定向

是的,是重定向问题……正当我百思不得其解的时候,忽然看到返回 res 里的请求体,我惊奇的发现居然是 get ???
我发出的请求不是 post 吗?

我忽然意识到,302就是重定向码啊。顺着这个思路着我又从 axios 的默认配置中看到这一点。

1
2
3
4
5
// `maxRedirects` defines the maximum number of redirects to follow in node.js.
// If set to 0, no redirects will be followed.
{
maxRedirects: 5, // default
}

yep,就是这里,axios 在 node 端默认会自动重定向请求,所以并不是没有得到请求,而是 axios 自动就重定向了。。。。。。

总结

本来这个问题应该是很简单的,可惜我见识不够。愣是花了好些时间在这上面。真是MDZZ。