请求有效,而URLFetch则没有

bge*_*hel 3 python google-app-engine urlfetch python-requests

我正试图在谷歌应用程序引擎应用程序中向python中的粒子服务器发出请求.

在我的终端中,我可以简单而成功地完成请求,如下所示:

res = requests.get('https://api.particle.io/v1/devices', params={"access_token": {ACCESS_TOKEN}})
Run Code Online (Sandbox Code Playgroud)

但在我的应用程序中,同样的事情不适用于urlfetch,它一直告诉我它无法找到访问令牌:

    url = 'https://api.particle.io/v1/devices'
    payload = {"access_token": {ACCESS_TOKEN}}
    form_data = urllib.urlencode(payload)
    res = urlfetch.fetch(
        url=url,
        payload=form_data,
        method=urlfetch.GET,
        headers={
            'Content-Type':
            'application/x-www-form-urlencoded'
        },
        follow_redirects=False 
    )
Run Code Online (Sandbox Code Playgroud)

我不知道问题是什么,也没办法调试.谢谢!

小智 10

简而言之,您的问题是,在您的urlfetch示例中,您将访问令牌嵌入到请求正文中,并且由于您发出了GET请求 - 它无法携带任何请求正文 - 这些信息将被丢弃.

为什么你的第一个片段有效?

因为requests.get()这个可选params参数意味着:"把这个字典我给你,把它的所有键/值对转换成一个查询字符串并将它附加到主URL"

所以,在窗帘后面,requests.get()正在构建一个这样的字符串:

https://api.particle.io/v1/devices?access_token=ACCESS_TOKEN

这是您应该将GET请求指向的正确端点.

你的第二个片段为什么不起作用?

这一次,urlfetch.fetch()使用不同的语法requests.get()(但仍然相同).这里需要注意的重要一点是,payload参数与我们之前使用过的参数并不相同.paramsrequests.get()

urlfetch.fetch()我们希望我们的查询字符串-if any-已经被urlencoded到URL中(这就是为什么urllib.urlencode()在这里发挥作用).另一方面,payload您应该将请求主体放在发出POST,PUT或PATCH请求的位置,但是particle.io的端点不期望您的OAuth访问令牌在那里.

这样的事情应该有效(免责声明:未经测试):

auth = {"access_token": {ACCESS_TOKEN}}
url_params = urllib.urlencode(auth)
url = 'https://api.particle.io/v1/devices?%s' % url_params

res = urlfetch.fetch(
    url=url,
    method=urlfetch.GET,
    follow_redirects=False 
)
Run Code Online (Sandbox Code Playgroud)

请注意我们现在不再需要您之前的Content-type标题了,因为我们毕竟没有携带任何内容.因此,headers可以从此示例调用中删除参数.

有关进一步的参考,请查看urlfetch.fetch() 参考此SO线程,这将有助于您更好地了解HTTP方法,参数和请求体,而不是我在这里的不良解释.

PS:如果particle.io服务器支持它(他们应该),你应该远离这个身份验证模式,Authorization: Bearer <access_token>而是在标题中携带你的标记.在URL中携带访问令牌并不是一个好主意,因为它们以这种方式更加明显并且倾向于保持登录服务器,因此存在安全风险.另一方面,在TLS会话中,所有请求标头始终都是加密的,因此您的身份验证令牌在那里很好地隐藏.