Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DateTime fields cause 500s as query parameters #49

Open
aetherknight opened this issue Feb 23, 2017 · 2 comments
Open

DateTime fields cause 500s as query parameters #49

aetherknight opened this issue Feb 23, 2017 · 2 comments

Comments

@aetherknight
Copy link

Endpoints and/or protorpc triggers a 500 error if a DateTime field is used as a query parameter instead of in the body of a request.

Reference Code

import endpoints
from protorpc import message_types, messages, remote


class BodyMessage(messages.Message):
    body_date = message_types.DateTimeField(1)


@endpoints.api(
    name='someapi',
    version='v1',
    allowed_client_ids=[endpoints.API_EXPLORER_CLIENT_ID],
    scopes=[endpoints.EMAIL_SCOPE]
)
class SomeApiService(remote.Service):

    QUERY_RESOURCE = endpoints.ResourceContainer(message_types.VoidMessage, query_date=message_types.DateTimeField(1))

    @endpoints.method(QUERY_RESOURCE, message_types.VoidMessage, path='get', http_method='GET', name='get')
    def get(self, request):
        print request.query_date
        return message_types.VoidMessage()

    @endpoints.method(BodyMessage, message_types.VoidMessage, path='post', http_method='POST', name='post')
    def post(self, request):
        print request.body_date
        return message_types.VoidMessage()


APPLICATION = endpoints.api_server([SomeApiService])

DateTime in a JSON body works as expected

When the post method is called with the date time in the JSON body in an ISO 8601-like format, it works fine:
datetime_body

DateTime as a query parameter generates erroneous APIs Explorer UI that causes 500s

However, when a datetime is in a query parameter, the endpoints API specification tells APIs explorer to show the fields that make up the DateTimeField type instead of a single string field:
datetime_query

If I try to supply what I would think is a valid DateTime in milliseconds since the epoch and timezone offset, I get a 500 error:

ERROR    2017-02-23 15:30:56,505 wsgi.py:279]
Traceback (most recent call last):
  File "/Users/wsorvis/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 268, in Handle
    for chunk in result:
  File "/Users/wsorvis/src/datatheorem/endpoints_sample/lib/endpoints/endpoints_dispatcher.py", line 117, in __call__
    yield self.dispatch(request, start_response)
  File "/Users/wsorvis/src/datatheorem/endpoints_sample/lib/endpoints/endpoints_dispatcher.py", line 149, in dispatch
    return self.call_backend(request, start_response)
  File "/Users/wsorvis/src/datatheorem/endpoints_sample/lib/endpoints/endpoints_dispatcher.py", line 350, in call_backend
    body_iter = self._backend(transformed_environ, start_response_proxy.Proxy)
  File "/Users/wsorvis/src/datatheorem/endpoints_sample/lib/endpoints/apiserving.py", line 428, in __call__
    body_iter = self.service_app(environ, start_response_proxy.Proxy)
  File "/Users/wsorvis/google-cloud-sdk/platform/google_appengine/lib/protorpc-1.0/protorpc/wsgi/util.py", line 173, in first_found_app
    response = app(environ, first_found_start_response)
  File "/Users/wsorvis/google-cloud-sdk/platform/google_appengine/lib/protorpc-1.0/protorpc/wsgi/service.py", line 148, in protorpc_service_app
    remote_info.request_type, environ['wsgi.input'].read(content_length))
  File "/Users/wsorvis/google-cloud-sdk/platform/google_appengine/lib/protorpc-1.0/protorpc/remote.py", line 1121, in decode_message
    return self.__protocol.decode_message(message_type, encoded_message)
  File "/Users/wsorvis/google-cloud-sdk/platform/google_appengine/lib/protorpc-1.0/protorpc/protojson.py", line 201, in decode_message
    message = self.__decode_dictionary(message_type, dictionary)
  File "/Users/wsorvis/google-cloud-sdk/platform/google_appengine/lib/protorpc-1.0/protorpc/protojson.py", line 279, in __decode_dictionary
    valid_value.append(self.decode_field(field, item))
  File "/Users/wsorvis/src/datatheorem/endpoints_sample/lib/endpoints/protojson.py", line 106, in decode_field
    return super(EndpointsProtoJson, self).decode_field(field, value)
  File "/Users/wsorvis/google-cloud-sdk/platform/google_appengine/lib/protorpc-1.0/protorpc/protojson.py", line 312, in decode_field
    return util.decode_datetime(value)
  File "/Users/wsorvis/google-cloud-sdk/platform/google_appengine/lib/protorpc-1.0/protorpc/util.py", line 463, in decode_datetime
    time_zone_match = _TIME_ZONE_RE.search(encoded_datetime)
TypeError: expected string or buffer
INFO     2017-02-23 15:30:56,513 module.py:806] default: "GET /_ah/api/someapi/v1/get?query_date.milliseconds=0&query_date.time_zone_offset=0 HTTP/1.1" 500 -

Note: Locally on the dev_appserver and both endpoints 1 and endpoints-2.0.2, if I send the query without using the fields from APIs Explorer, then it works as expected. Eg, the URL http://localhost:8080/_ah/api/someapi/v1/get?query_date=2017-01-01T00:00:00 responds with a 204 (and it prints the supplied date).

When deployed to appengine with endpoints 1, trying to submit a string to the query_date directly causes a 500 that does not show up in my logs. I have not tested endpoints 2 when deployed yet.

Expected Behavior

the endpoints API description provided to APIs Explorer should expose a datetime query parameter as a string field, the same way it does when a datetime field is in the body.

@aetherknight
Copy link
Author

To clarify further, there are 2 problems:

  • the endpoints API definition does not describe DateTimes in query parameter fields in a way that the APIs explorer handles nicely
  • When deployed, Endpoints 2 behaves fine if I ignore APIs explorer and send the query parameter as an ISO-8601 string. However, the same request but with Endpoints 1 (when deployed to GAE) 500s and does not give me a stack track trace.

@mchalek
Copy link

mchalek commented Apr 19, 2017

I ran into the same problem today. I put a log message into protorpc util.py to see what was being passed to the decoded_datetime function, and it's a dictionary with the milliseconds and time_zone_offset arguments as keys. Of course, that method expects a string argument.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants