blogs icon indicating copy to clipboard operation
blogs copied to clipboard

记一次坑爹的对接经历

Open yibuyisheng opened this issue 9 years ago • 1 comments

事情是这样的:

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

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

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 函数改成这样:

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、请求未成功发送出去等等),很可能不显示完整的请求头,不显示响应信息(因为按照语义,此时根本无响应信息可显示)。

yibuyisheng avatar May 07 '15 05:05 yibuyisheng

有追求的程序员就应该这样。

jikeytang avatar May 07 '15 05:05 jikeytang