【问题标题】:URLFetch does not support granular timeout settings, reverting to total or default URLFetch timeoutURLFetch 不支持粒度超时设置,恢复为总或默认 URLFetch 超时
【发布时间】:2020-04-15 05:02:32
【问题描述】:

我们有一个基于 python2.7 标准谷歌应用引擎的应用程序 (app-a)。我们正在尝试使用基于示例here 的服务帐户进行编程身份验证以访问另一个应用程序(app-b)。 app-b 在 python3.7 标准谷歌应用引擎上。

当我们进行 iap 认证调用时,我们在 App-A 的日志中收到以下错误。

resp = requests.request(
    method, url,
    headers={'Authorization': 'Bearer {}'.format(
        google_open_id_connect_token)}, **kwargs)

AppEnginePlatformWarning: urllib3 is using URLFetch on Google App Engine sandbox instead of sockets. To use sockets directly instead of URLFetch see https://urllib3.readthedocs.io/en/latest/reference/urllib3.contrib.html.

AppEnginePlatformWarning: URLFetch does not support granular timeout settings, reverting to total or default URLFetch timeout.

requests.request 错误与

 Exception("Bad response from application: 500 / {'content-type': 'text/html', 'x-cloud-trace-context':

在 App-B 中,我们尝试接收从 app-a 发送的数据。

json.loads(request.data)

我们在app-b的日志中得到以下错误。

in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/opt/python3.7/lib/python3.7/json/decoder.py", line 355, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

这让我相信 app-a 能够成功调用 app-b。但由于某种原因,它无法传递数据。请帮忙。

更新 - 根据使用 HTTPlib 的建议,我们尝试了这个。

payload = {
    'test_data' : "data_test"
}

payload_json_dumps = json.dumps(payload)


conn = httplib.HTTPConnection(host)
conn.request("POST", path, payload_json_dumps, request_headers)
resp = conn.getresponse()

在 app.yaml 中添加了以下内容。

env_variables:
  GAE_USE_SOCKETS_HTTPLIB : 'true'

在 App-B 中我们改为

from flask import request

@app.route('url', methods = ['GET','POST'])
def content_from_client(): 
    if (request.data):
        data_received = request.get_json()

我们仍然无法获取 App-B 上的数据。我们得到

AttributeError("'NoneType' object has no attribute 'get'")

更新 -

更改了标题格式并使其正常工作。

   request_headers = {
        "Content-Type": 'application/json', 
        "follow_redirects": False,
        "X-Appengine-Inbound-Appid": "app-A.appspot.com",
        "Connection": "keep-alive",
        'Authorization': 'Bearer {}'.format(google_open_id_connect_token)
    }

【问题讨论】:

  • 您发送的数据是什么?发送前是否致电json.dumps(data)
  • 我们在发送数据之前做了一个 json.dumps(payload)。

标签: python-3.x python-2.7 google-app-engine urllib3 urlfetch


【解决方案1】:

AppEnginePlatformWarningrequests library 使用的 urllib3 引发。

Urllib3 提供了一个默认使用URL Fetch API 的池管理器。虽然有时可能不是您的用例的最佳选择。一种解决方案是改用套接字。为此,您必须配置您的 app.yaml 并包含以下字段:

env_variables:
    GAE_USE_SOCKETS_HTTPLIB : 'true'

您还可以在 Google documentation 中找到此文档。

对于您的应用程序 B 上的错误,我将使用 response.json() 方法,requests 内置方法而不是 json.loads(),因为它会自动检测要使用的解码器。

如果这有帮助,请告诉我。

【讨论】:

  • 感谢您的回复。您能否解释一下为什么 URLFetch 在这种情况下不起作用?当您说“Urllib3 提供了一个池管理器......有时这可能不是您的用例的最佳选择。”你能解释一下这是什么意思吗?我们是否必须必须使用套接字?这是一个低级别的实现,我们想避免它。我们可以为 URLFetch 设置任何其他参数来进行 POST 调用吗?这似乎是非常基础的。看起来 app-A 正在成功调用 app-B - 只是无法传递数据。感谢您的建议 response.json()。
  • 我不熟悉 URLFetch 的具体工作原理,但您可以在 Github issue 中找到更多信息,其中指出为了建立 HTTPS 连接,您应该使用套接字 API 而不是 URLFetch。
  • 我已启用计费并添加了 GAE_USE_SOCKETS_HTTPLIB: 'true' 我仍然收到 AppEnginePlatformWarning
【解决方案2】:

以下建议有助于解决问题。改为 httplib 而不是 urlfetch。

conn = httplib.HTTPConnection(host)
conn.request("POST", path, payload_json_dumps, request_headers)
resp = conn.getresponse()

将以下内容添加到 app.yaml -

 env_variables:
    GAE_USE_SOCKETS_HTTPLIB : 'true'

将标题格式更改为 -

  request_headers = {
        "Content-Type": 'application/json', 
        "follow_redirects": False,
        "X-Appengine-Inbound-Appid": "app-A.appspot.com",
        "Connection": "keep-alive",
        'Authorization': 'Bearer {}'.format(google_open_id_connect_token)
    }

【讨论】:

    猜你喜欢
    • 2012-10-30
    • 1970-01-01
    • 2011-01-10
    • 2011-05-06
    • 1970-01-01
    • 2014-03-09
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    相关资源
    最近更新 更多