问题
In the python standard environment quickstart, the endpoints method test_api_key returns a 503 Service Unavailable. The error occurs in the API Explorer when run with dev_appser.py and when the API is deployed. The code for it is:
import endpoints
from protorpc import message_types
from protorpc import messages
from protorpc import remote
class TestResponse(messages.Message):
content = messages.StringField(1)
@endpoints.api(name='practice', version='v1', description='My Practice API')
class PracticeApi(remote.Service):
@endpoints.method(
message_types.VoidMessage,
TestResponse,
path='test/getApiKey',
http_method='GET',
name='test_api_key')
def test_api_key(self, request):
return TestResponse(content=request.get_unrecognized_field_info('key'))
api = endpoints.api_server([PracticeApi])
I don't have a good understanding of .get_unrecognized_field_info('key') so I am not sure what the issue is? Thanks.
回答1:
Firstly, I recommend reading Google Protocol RPC Library Overview, since it's Google Cloud Endpoints uses it extensively.
@endpoints.method allows you to configure a specific method in your API. Configuration options are documented in Google Cloud Platform documentation Creating an API with Cloud Endpoints Frameworks for App Engine, in the section, Defining an API method (@endpoints.method).
If you're restricting access to the test/getApiKey/test_api_key
method, then you must configure the method with the api_key_required=True
option. Restricting API Access with API Keys (Frameworks) discusses that further, but your method annotation should be:
@endpoints.method(
message_types.VoidMessage,
TestResponse,
path='test/getApiKey',
http_method='GET',
name='test_api_key',
api_key_required=True
)
Notice your method accepts a request parameter representing the HTTP request (i.e. client using your API):
def test_api_key(self, request):
However, the request
parameter is actually Google Protocol RPC Message (Proto RPC) Message object and as such is very well defined. If additional fields exist in the ProtoRPC request parameter, beyond what is formally defined, they are still stored with the request object but must be retrieved using the following method:
def get_unrecognized_field_info(self, key, value_default=None,
variant_default=None):
"""Get the value and variant of an unknown field in this message.
Args:
key: The name or number of the field to retrieve.
value_default: Value to be returned if the key isn't found.
variant_default: Value to be returned as variant if the key isn't
found.
Returns:
(value, variant), where value and variant are whatever was passed
to set_unrecognized_field.
"""
Message class code on GitHub is quite well documented. .
No arguments will appear in the body of a request because you've configured the method with to be called with HTTP GET:
http_method='GET'
...you're correctly using the value message_types.VoidMessage
.
In terms of your error, 503 is just a generic server error, can you provide any information from the StackDriver logs? They will point you to the exact line and error in your code.
回答2:
There were three things that were creating the 503 error.
Firstly, I needed to make the method or entire Api require an Api Key. In this case I just applied it to the entire Api:
@endpoints.api(name='practice', version='v1', api_key_required=True)
class PracticeApi(remote.Service):
Secondly, after I generated the Api Key in the cloud console I needed to put the Key into the openapi.json file before deploying it.
Lastly, I was still getting a validation error:
ValidationError: Expected type <type 'unicode'> for field content, found (u'My Api Key', Variant(STRING, 9)) (type <type 'tuple'>)
The get_unrecognized_field_info() function returns a tuple of (value, variant). A tuple was not expected by the response so I updated the method to only show value:
def test_api_key(self, request):
return TestResponse(content=request.get_unrecognized_field_info('key')[0])
来源:https://stackoverflow.com/questions/42520630/google-cloud-endpoints-python-quickstart-echo-sample-issue