Repository navigation
DateTime fields cause 500s as query parameters #49
Description
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 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:

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.
Activity
aetherknight commentedon Feb 23, 2017
To clarify further, there are 2 problems:
mchalek commentedon 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
millisecondsandtime_zone_offsetarguments as keys. Of course, that method expects a string argument.