Python 使用 POST 和 urllib2 访问 Web API

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4195325/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 14:43:24  来源:igfitidea点击:

Using POST and urllib2 to access web API

pythonhttpposturllib2

提问by neomech

I am trying to access a web API using a POST technique. I AM able to access it using a GET technique, but the API owners tell me that certain functionality only works with POST. Unfortunately I can't seem to get POST working.

我正在尝试使用 POST 技术访问 Web API。我可以使用 GET 技术访问它,但 API 所有者告诉我某些功能仅适用于 POST。不幸的是,我似乎无法让 POST 工作。

Here's what works with GET:

以下是 GET 的作用:

API_URL = "http://example.com/api/"

def call_api(method, **kwargs):
    url = API_URL + method
    if kwargs:
        url += '?' + urllib.urlencode(kwargs)
    req = urllib2.Request(url)
    auth = 'Basic ' + base64.urlsafe_b64encode("%s:%s" % (USER, PASS))
    req.add_header('Authorization', auth)
    return urllib2.urlopen(req)

Here's what does NOT work with POST (causes HTTP 400 error):

以下是不适用于 POST 的内容(导致 HTTP 400 错误):

API_URL = "http://example.com/api/"

def call_api(method, **kwargs):
    url = API_URL + method
    data=''
    if kwargs:
        data=urllib.urlencode(kwargs)
    req = urllib2.Request(url, data)
    auth = 'Basic ' + base64.urlsafe_b64encode("%s:%s" % (USER, PASS))
    req.add_header('Authorization', auth)
    return urllib2.urlopen(req)

Does anything jump out at anyone as being inherently incorrect in the POST code? I've never done a POST call before but everything I've read seems to suggest that my code is reasonable. Is there some different way I'm supposed to do the add_header thing for the authorization if I'm using POST?

任何人都会因为 POST 代码中的固有错误而跳出任何东西吗?我以前从未做过 POST 调用,但我读过的所有内容似乎都表明我的代码是合理的。如果我使用 POST,是否有一些不同的方式我应该为授权做 add_header 事情?

采纳答案by sneeu

With urllib2you need to add the data to the POSTbody:

随着urllib2您需要将数据添加到POST身体:

def call_api(method, **kwargs):
    url = API_URL + method
    req = urllib2.Request(url)

    if kwargs:
        req.add_data(urllib.urlencode(kwargs))

    auth = 'Basic ' + base64.urlsafe_b64encode("%s:%s" % (USER, PASS))
    req.add_header('Authorization', auth)

    # req.get_method() -> 'POST'

    return urllib2.urlopen(req)

回答by bgporter

As @sneeu notes above, it's the act of adding the data to be posted to the request that converts the request from a GET into a POST.

正如上面@sneeu 所指出的,将要发布的数据添加到请求中的行为将请求从 GET 转换为 POST。

However, this still assumes that what the API is expecting to receive in the POST body is form-encoded data. Many more recent APIs that I've worked with are expecting something else in there (XML or JSON, most commonly).

但是,这仍然假设 API 期望在 POST 正文中接收的是表单编码数据。我使用过的许多最近的 API 都在期待其他东西(最常见的是 XML 或 JSON)。

Can you verify what that API is expecting to receive as a data payload?

您能否验证该 API 期望接收的数据负载是什么?

回答by fandyst

I have faced the same problem, I want to send data with the POST method of HTTP, but after dir(req)I found get_method, but no set_method, and I also found there is a property called data, so try this out:

我遇到了同样的问题,我想用HTTP的POST方法发送数据,但是dir(req)我发现之后get_method,却没有set_method,而且我还发现有一个属性叫做data,所以试试这个:

>>> req.data={"todototry":"123456"}
>>> req.get_method()
'POST'
>>>

Thanks @sneeu.

谢谢@sneeu。