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

Replace POST request from Requests to urrlib cause 404 Error

我有一个用 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/python3.8/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.8/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/usr/lib/python3.8/urllib/request.py", line 640, in http_response
    response = self.parent.error(
  File "/usr/lib/python3.8/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/usr/lib/python3.8/urllib/request.py", line 502, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.8/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)

...

method should be a string that indicates the HTTP request method that will be used (e.g. 'HEAD'). If provided, its value is stored in the method attribute and is used by get_method(). The default is 'GET' if data is None or 'POST' otherwise. Subclasses may indicate a different default method by setting the method attribute in the class itself.

所以使用

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

应该可以。