事情是这样的:

后端提供了一个数据接口 /account/my/address/ 。咱是有追求的程序员,自然接口要采用 RESTful 的思想,于是服务器端非成功的处理,都会返回 http code 非200的状态码,坑由此而生。

在前端请求这个地方,由于做的是移动端应用,果断采用了手写 xhr 请求,大致接口请求代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function encodeParams(params) {
var paramsStr = [];
for (var k in params) {
paramsStr.push(k + '=' + params[k]);
}
return paramsStr.join('&');
}
function post(url, params) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.onload = function() { resolve(xhr.response); };
xhr.onerror = function() { reject(xhr.response); };
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(encodeParams(params));
});
}
post('/account/my/address/', {/*参数*/})
.then(function(response) {
// some code
});

代码写好,拿到 chrome 中一测,出现一个似乎像是请求没发出去的错误:

对于当时不知道 chrome://net-internals/ 这个强大工具的我来说,这种错误简直就是一个莫名其妙的东西,很难搞。

于是仔细看一眼 request header ,发现没有 Content-Length !这是怎么回事?为什么浏览器没计算出来 Content-Length ?很不可思议!

于是,尝试改变一下请求 body 的编码方式,将上述 post 函数改成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function createFormData(params) {
var fd = new FormData();
for (var k in params) {
fd.append(k, params[k]);
}
return fd;
}
function post(url, params) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.onload = function() { resolve(xhr.response); };
xhr.onerror = function() { reject(xhr.response); };
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
xhr.send(createFormData(params));
});
}

再测,出现这样的错:

仍然没有 Content-Length ,错误依旧,简直令人发指!

于是重新审视当前的开发模式,整个结构是这样的:我在本地开发前端静态部分,需要数据的时候通过 xhr 请求到后端去请求,为了避免我本地开发的时候还要启动一个后端服务器程序,于是让后端的同学将后端代码部署在一个公网的服务器上,这样我就可以通过代理或者 CORS 的方式来请求相应的接口了。

所以此时此刻,有点怀疑是不是这种模式引发的问题,但是再一想,其它很多获取数据提交数据都是这种模式啊,为啥就正常呢!所以这种怀疑被打消。

chrome 的开发者工具提供的信息太有限,实在想不出来是什么问题,于是到 QQ 群求助网友,其中一位网页给出了这个: chrome://net-internals/ ,抱着试一试的心态,打开,观察,哇咔咔,好牛逼,请求的各个过程尽收眼底!其中我找到了我的 POST 请求:

嗯,看来请求还是被正常发送出去了的。再往下看,发现了这个:

ERR_UNEXPECTED_PROXY_AUTH 映入眼帘,代理需要认证?啥玩意儿?然后再看到一个 Server: nginx/1.4.6 (Ubuntu) ,仔细想想,为毛 nginx 会说代理认证错误!抓狂,去找后端人员,后端人员果断说不可能是 nginx 有问题!

于是,再次崩溃, google 吧!于是尝试各种关键字搜索: ERR_UNEXPECTED_PROXY_AUTHnet_error = -323

搜索的时候,出现了一条关于 http code 407 的记录,点进去一看,惊呆了, 407 的含义如下:

Proxy Authentication Required

需要代理授权!再看看上面的那张图,后端返回的 http code 果然是407,于是找到后端人员,问他可能会返回407吗?答案是 yes !(我“怒发冲冠”,于是后端同学,卒)

总结

这次问题解决总结下来有这么几个点,以后要注意:

  • 1、在 RESTful 开发中,一定要对状态码足够敏感;
  • 2、好好使用 chrome://net-internals/ ,确实挺强大;
  • 3、chrome 出现上述类似错误的时候(407、请求未成功发送出去等等),很可能不显示完整的请求头,不显示响应信息(因为按照语义,此时根本无响应信息可显示)。