使用requests包调用REST HTTP服务:GET请求失败POST可行,求原因
问题解析:urllib2与requests请求REST服务的差异原因
嘿,这个问题其实是因为你用urllib2和requests时,实际发送的HTTP请求方法以及请求行为不一致导致的,我给你拆解下细节:
1. 你的urllib2代码实际发送的是POST请求
你可能以为自己用urllib2发的是GET,但仔细看这段代码:
r = urllib2.Request("http://myServer.com:12345/myAction") data = json.dumps(q) #q是Python字典 r.add_data(data) r=urllib2.urlopen(r)
调用r.add_data(data)的核心作用是给请求添加请求体(Body),而urllib2的默认规则是:只要给Request对象设置了请求体,就会自动把请求方法从默认的GET改成POST。所以这段代码本质是在发送POST请求,和服务器接口的要求匹配,自然能正常获取数据。
2. 第一次用requests的GET请求为什么失败?
你写的这段代码:
r=requests.get("http://myServer.com:12345/myAction", data=q)
明确指定了用GET方法发送请求。虽然HTTP规范本身没有禁止GET请求带请求体,但绝大多数REST服务(包括你的myServer)都不支持这种用法——因为GET请求的设计初衷是用于获取资源,通常参数都是放在URL的查询字符串里,而不是请求体中。你的服务器接口只接受POST请求,所以收到这种不符合常规的GET请求时,就返回了“方法不被允许”的提示。
3. 改用POST请求正常的原因
当你换成这段代码:
r=requests.post("http://myServer.com:12345/myAction", data=json.dumps(q))
你发送的是POST请求,而且请求体的格式和urllib2代码完全一致(都是JSON格式的字符串),刚好匹配服务器接口的要求,所以就能正常获取数据了。
小补充:requests更简洁的传JSON方式
其实requests自带了处理JSON请求体的便捷方式,你不用手动调用json.dumps(q),直接用json参数即可,requests会自动帮你序列化字典、设置正确的Content-Type请求头:
r = requests.post("http://myServer.com:12345/myAction", json=q)
这样写更简洁,也能避免手动序列化可能出现的小问题。
内容的提问来源于stack exchange,提问作者user1008636
相关产品推荐
相关产品推荐

