【问题标题】:Requests works and URLFetch doesn't请求有效,而 URLFetch 无效
【发布时间】:2015-07-15 21:20:29
【问题描述】:

我正在尝试在谷歌应用引擎应用程序中向 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 
    )

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

【问题讨论】:

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


    【解决方案1】:

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

    为什么您的第一个 sn-p 有效?

    因为requests.get() 采用可选的params 参数,这意味着:“使用我给你的这本字典,将其所有键/值对转换为query string 并将其附加到主URL”

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

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

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

    为什么你的第二个 sn-p 不起作用?

    这一次,urlfetch.fetch() 使用了与requests.get() 不同的语法(但仍然是等效的)。这里需要注意的重要一点是payload 参数与我们之前在requests.get() 中使用的params 参数的含义相同。

    urlfetch.fetch() 期望我们的查询字符串 - 如果有的话 - 已经被 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 方法、参数和请求正文有更好的了解,而不是我在此处的拙劣解释。

    PS:如果particle.io 服务器支持它(它们应该),您应该远离此身份验证架构,并在Authorization: Bearer <access_token> 标头中携带您的令牌。在 URL 中携带访问令牌不是一个好主意,因为这样它们更容易看到,并且往往会保持登录在服务器中,因此会带来安全风险。另一方面,在 TLS 会话中,所有请求标头始终被加密,因此您的身份验证令牌很好地隐藏在那里。

    【讨论】:

    • 是的,就是这样;比我下面的答案更详细。谢谢!!
    • 我明白了;我正在保护它,所以它不是服务器中的纯文本,但我没有考虑 url 发送本身。再次感谢。
    【解决方案2】:

    好吧,事实证明,不能为使用 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 
    )
    

    这对我有用。

    【讨论】:

      猜你喜欢
      • 2017-10-30
      • 1970-01-01
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 2014-09-18
      • 2023-03-19
      • 1970-01-01
      • 2023-03-14
      相关资源
      最近更新 更多