解决问题的过程

在快速开发中,没有精力完善单元测试,但为了调试、验证,按网络连接的会话流程,写了测试用的python脚本。

脚本执行的过程是,

1、调用登录接口,获取cookie

2、使用数据接口时,在header中设置这个cookie,才能正常访问。

使用了requests包做http请求,很方便。

但在部署核心集群时遇到了问题:

由于限制使用外网,无法通过yum、easy_install来更新服务器、python依赖的操作.

好在python的内置库还有urllib2和urllib,可以替换requests,印象里调用过程差别不大。这样的改动成本,比手动安装依赖小。

改写

简单修改后,总是返回登录异常。

通过wireshark抓包,发现:

把post数据的字典,直接转换为字符串,发送请求就是上图的样子。

请求参数都挤在key里面,value是空的;要想正常的post数据字典,应该加上urllib.urlencode(data)。

连接值

登录鉴权发送正常了,数据接口请求还是失败。

打印鉴权请求返回的header,并没有cookie,获取不到cookie,就不能调用后面的接口。

于是我又对比了requests和urllib2 两者发送请求的异同,我发现,requests发送的headers里面,连接值为“keep-alive”,而urllib2发送连接值为“close”。

我以为这就是问题所在,查了大量修改header的连接值(Connection)的方法,答案却是无解。

这是因为,虽然urllib2保留了设置header参数的接口,但是对于连接值,是硬编码到内置代码里的,无论如何显式修改,实际的连接值只能是“close”。

urllib2如此设计的初衷,是为了避免一处bug,不细说了。不过对于一些场景,确实非常不便,比如用到长连接的FTP下载。

cookie

这些不便的场景里,其实不包括登录。

清醒的想一下,urllib2是个老古董,但也是纵横多年的python内置依赖,怎么可能一个简单的登录会话都完成不了?连接值只是控制http请求是长连接还是短连接,而和登录会话没有关系吧,毕竟我只是要获取cookie而已啊。

改变了思路,谷歌转而搜索“urllib2 登录”,很容易搜到现成代码。

原来,在urllib2,cookie的管理是分离的,需要引入cookielib,对urllib2加一些配置,登录行为后就可以会保存cookie,在之后的会话中默认自动在header中设置。

之前抓包过程中,我只看了登录的post请求,没有查看登录接口的返回,所以忽略了后面的关键线索。

而一个完整的登录请求会话,是“发送post请求”、“接收到客户端302跳转”、“发送get请求”、“接收到返回200”,只要看一下后续的请求和返回,就不会把问题定位到无关的连接值。

对urllib2做设置之后,整个会话就没有问题了。

搞定之后,觉得还是用requests更清新、友好,顺便熟悉了一下wireshark,收获不小。

重要的经验是,分析具体问题中,不要忘记常识,避免走到与真实问题无关的死胡同。

-END-

赞赏一下作者吧~

关注作者吧~

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180405G08BDU00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注腾讯云开发者

领取腾讯云代金券