【问题标题】:HTTP Deadline exceeded waiting for python Google Cloud Endpoints on python client localhost在 python 客户端 localhost 上等待 python Google Cloud Endpoints 超出 HTTP 截止日期
【发布时间】:2016-02-21 20:45:08
【问题描述】:

我想构建一个 python 客户端来与我的 python Google Cloud Endpoints API 对话。我的简单 HelloWorld 示例在 python 客户端中遇到了 HTTPException,我不知道为什么。

我已经按照this 非常有用的线程中的建议设置了简单的示例。 GAE Endpoints API 在 localhost:8080 上运行没有问题 - 我可以在 API Explorer 中成功访问它。在我添加有问题的 service = build() 行之前,我的简单客户端在 localhost:8080 上运行良好。

当试图让客户端与端点 API 对话时,我收到以下错误:

File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/dist27/gae_override/httplib.py", line 526, in getresponse
raise HTTPException(str(e))
HTTPException: Deadline exceeded while waiting for HTTP response from URL: http://localhost:8080/_ah/api/discovery/v1/apis/helloworldendpoints/v1/rest?userIp=%3A%3A1

我已尝试延长 http 截止日期。这不仅没有帮助,而且如此简单的首次调用 localhost 不应超过默认的 5 秒截止日期。我也试过直接在浏览器中访问发现 URL,效果也很好。

这是我的简单代码。首先是客户端,main.py:

import webapp2
import os
import httplib2

from apiclient.discovery import build

http = httplib2.Http()

# HTTPException happens on the following line:
# Note that I am using http, not https
service = build("helloworldendpoints", "v1", http=http, 
  discoveryServiceUrl=("http://localhost:8080/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest"))

# result = service.resource().method([parameters]).execute()

class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-type'] = 'text/plain'
        self.response.out.write("Hey, this is working!")

app = webapp2.WSGIApplication(
    [('/', MainPage)],
    debug=True)

这里是 Hello World 端点,helloworld.py:

"""Hello World API implemented using Google Cloud Endpoints.

Contains declarations of endpoint, endpoint methods,
as well as the ProtoRPC message class and container required
for endpoint method definition.
"""
import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote


# If the request contains path or querystring arguments,
# you cannot use a simple Message class.
# Instead, you must use a ResourceContainer class
REQUEST_CONTAINER = endpoints.ResourceContainer(
    message_types.VoidMessage,
    name=messages.StringField(1),
)


package = 'Hello'


class Hello(messages.Message):
    """String that stores a message."""
    greeting = messages.StringField(1)


@endpoints.api(name='helloworldendpoints', version='v1')
class HelloWorldApi(remote.Service):
    """Helloworld API v1."""

    @endpoints.method(message_types.VoidMessage, Hello,
      path = "sayHello", http_method='GET', name = "sayHello")
    def say_hello(self, request):
      return Hello(greeting="Hello World")

    @endpoints.method(REQUEST_CONTAINER, Hello,
      path = "sayHelloByName", http_method='GET', name = "sayHelloByName")
    def say_hello_by_name(self, request):
      greet = "Hello {}".format(request.name)
      return Hello(greeting=greet)

api = endpoints.api_server([HelloWorldApi])

最后,这是我的 app.yaml 文件:

application: <<my web client id removed for stack overflow>>
version: 1
runtime: python27
api_version: 1
threadsafe: yes

handlers:

- url: /_ah/spi/.*
  script: helloworld.api
  secure: always

# catchall - must come last!
- url: /.*
  script: main.app
  secure: always


libraries:

- name: endpoints
  version: latest

- name: webapp2
  version: latest

为什么我超过了 HTTP 截止日期以及如何解决?

【问题讨论】:

    标签: python-2.7 google-app-engine google-cloud-endpoints google-api-python-client httpexception


    【解决方案1】:

    在您的main.py 上,您忘记将一些变量添加到您的发现服务 url 字符串中,或​​者您只是在没有它的情况下复制了这里的代码。从外观上看,您可能假设使用格式字符串方法。

    "http://localhost:8080/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest".format(api='helloworldendpoints', apiVersion="v1")
    

    通过查看日志,您可能会看到如下内容:

    INFO     2015-11-19 18:44:51,562 module.py:794] default: "GET /HTTP/1.1" 500 -
    INFO     2015-11-19 18:44:51,595 module.py:794] default: "POST /_ah/spi/BackendService.getApiConfigs HTTP/1.1" 200 3109
    INFO     2015-11-19 18:44:52,110 module.py:794] default: "GET /_ah/api/discovery/v1/apis/helloworldendpoints/v1/rest?userIp=127.0.0.1 HTTP/1.1" 200 3719
    

    先超时,然后“工作”。

    在请求处理程序中移动服务发现请求:

    class MainPage(webapp2.RequestHandler):
        def get(self):
            service = build("helloworldendpoints", "v1",
                        http=http,
                        discoveryServiceUrl=("http://localhost:8080/_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest")
                        .format(api='helloworldendpoints', apiVersion='v1'))
    

    【讨论】:

    • 如果日志还没有使用 {api} 和 {apiVersion} 格式化,它是如何输出正确的 URL 的?尽管如此,日志的 ip (rest?userIp=%3A%3A1) 确实表明 ip 地址可能被搞砸了?奇怪,您的格式化技巧不起作用 - 尽管将用户 IP 指定为 127.0.0.1,但日志仍然返回完全相同的超时消息和相同的奇怪 IP
    • 是的,这就是为什么我说你可能复制错了,但我不得不添加它。这确实是一种异常的开发服务器行为。很耐人寻味。尝试去localhost:8080/_ah/api/discovery/v1/apis/helloworldendpoints/v1/…你得到正确的回应吗?
    • 是的,我通过该链接得到了正确的响应。如果我剪切/粘贴日志的错误 URL(带有rest?userIp=%3A%3A1 的 URL),我也会得到相同的正确响应。直接浏览器交互工作正常。我将您的代码剪切/粘贴到我的代码中,但仍然超时。你会明白为什么这会令人沮丧!
    • 我什至在http = httplib2.Http(timeout=40) 上将超时设置为 40 秒,所以这可能是一些泄漏抽象的情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-03
    • 1970-01-01
    • 1970-01-01
    • 2014-09-14
    • 2014-05-27
    • 2017-07-07
    相关资源
    最近更新 更多