请求有效,而URLFetch则没有

时间:2015-07-15 21:20:29

标签: python google-app-engine python-requests urlfetch

我正在尝试在google应用引擎应用中向python中的粒子服务器发出请求。

在我的终端中,我可以简单而成功地完成请求,请求为:

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

但在我的应用程序中,同样的事情不适用于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 
    )

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

2 个答案:

答案 0 :(得分:10)

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

为什么您的第一个代码段有效?

因为requests.get()采用了可选的params参数,这意味着:"拿这个我给你的字典,将其所有的键/值对转换为query string并将其附加到主要网址"

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

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

您应该将GET请求指向正确的端点。

为什么您的第二个代码段不起作用?

这一次,urlfetch.fetch()使用的语法与requests.get()不同(但仍然相同)。这里需要注意的重要一点是,payload参数不会与您之前在params中使用的requests.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 
)

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

如需进一步参考,请查看urlfetch.fetch() referencethis SO thread,希望能让您更好地了解HTTP方法,参数和请求正文,而不是我在这里的不良解释。< / p>

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

答案 1 :(得分:0)

好的,事实证明,使用Urlfetch的GET请求不能包含有效负载。相反,必须使用'?'在url中包含参数语法如下:

url = 'https://api.particle.io/v1/devices'
url = url + '?access_token=' + {ACCESS_TOKEN}
res = urlfetch.fetch(
    url=url,
    method=urlfetch.GET,
    follow_redirects=False 
)

这对我有用。