将请求中的POST请求替换为urrlib导致404错误

问题描述

我有一个代码,可以像这样requests打开门

from requests import post as req_post

HEADER = {"Authorization": Bearer 097....} # some private number
ACCESS_LINK= https://api.akerun.com/v5/organizations/.../jobs/unlock # some private link

x = req_post(ACCESS_LINK,headers=HEADER)
print(x.header)

将打开门,并用一些私人数据回复此类信息

{'Date': 'Tue,06 Oct 2020 01:14:15 GMT','Content-Type': 'application/json','Content-Length': '23','Connection': 'keep-alive','Server': 'Nginx','Strict-Transport-Security': 'max-age=31536000','ETag': ... Cache-Control': 'max-age=0,private,must-revalidate','Set-Cookie': ...,'X-Runtime': '0.185443'}

所以当我像这样用urllib

a = "https://api.akerun.com/v5/organizations/.../jobs/unlock"
b = {"Authorization": "Bearer 097..."}

from urllib import request,parse

req =  request.Request(a,headers=b) 
resp = request.urlopen(req)

它引发错误

Traceback (most recent call last):
  File "/home/suomi/kaoiro/kaoiro/test.py",line 10,in <module>
    resp = request.urlopen(req)
  File "/usr/lib/@R_502[email protected]/urllib/request.py",line 222,in urlopen
    return opener.open(url,data,timeout)
  File "/usr/lib/@R_502[email protected]/urllib/request.py",line 531,in open
    response = meth(req,response)
  File "/usr/lib/@R_502[email protected]/urllib/request.py",line 640,in http_response
    response = self.parent.error(
  File "/usr/lib/@R_502[email protected]/urllib/request.py",line 569,in error
    return self._call_chain(*args)
  File "/usr/lib/@R_502[email protected]/urllib/request.py",line 502,in _call_chain
    result = func(*args)
  File "/usr/lib/@R_502[email protected]/urllib/request.py",line 649,in http_error_default
    raise HTTPError(req.full_url,code,msg,hdrs,fp)
urllib.error.HTTPError: HTTP Error 404: Not Found

为什么? requests的请求与urllib的请求不同吗?

解决方法

问题很可能是urllib在您的情况下正在执行GET而不是POST请求。

来自docs

class urllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None)

...

方法应该是一个字符串,用于指示将要使用的HTTP请求方法(例如'HEAD')。如果提供,则其值存储在method属性中,并由get_method()使用。如果数据为'GET',则默认值为None,否则为'POST'。子类可以通过在类本身中设置method属性来指示不同的默认方法

因此使用

req = request.Request(a,headers=b,method='POST') 

应该可行。