0

Python Google Cloud Endpoints API と通信する Python クライアントを構築したいと考えています。私の単純な HelloWorld の例は、Python クライアントで HTTPException に苦しんでおり、その理由がわかりません。

この非常に役立つスレッドで提案されているように、簡単な例をセットアップしました。GAE エンドポイント 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 Deadline Exceeded が表示されるのはなぜですか? また、それを修正するにはどうすればよいですか?

4

1 に答える 1

1

ディスカバリ サービスの URL 文字列にいくつかの変数を追加するのmain.pyを忘れたか、コードをコピーせずにここにコピーしただけです。見た目からすると、おそらくフォーマット文字列メソッドを使用すると思われます。

"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'))
于 2015-11-19T17:36:03.237 に答える