cloudendpoints / endpoints-python

A Python framework for building RESTful APIs on Google App Engine
Apache License 2.0
51 stars 17 forks source link

Passing JSON value other than an object in request body results in 500 Internal Server Error #192

Open ppik opened 5 years ago

ppik commented 5 years ago

When the client sends a POST request that consists of any other JSON value besides a JSON object, e.g, a string or an array, the endpoints framework returns with 500 Internal Server Error. Would expert a 400 Bad Request error for parsing ProtoRPC request.

To reproduce, e.g., use the echo example. Example queries returning 500:

curl https://<YOUR-PROJECT-ID>.appspot.com/_ah/api/echo/v1/echo -H "Content-Type: application/json" -d '"hello world"'

curl https://<YOUR-PROJECT-ID>.appspot.com/_ah/api/echo/v1/echo -H "Content-Type: application/json" -d '["hello", "world"]'

Log message:

Traceback (most recent call last):
  File "/base/alloc/tmpfs/dynamic_runtimes/python27g/7679791231c143f9/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py", line 267, in Handle
    result = handler(dict(self._environ), self._StartResponse)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints_management/control/wsgi.py", line 166, in __call__
    return self.wsgi_backend(environ, start_response)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints_management/control/wsgi.py", line 278, in __call__
    return self._application(environ, start_response)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints_management/control/wsgi.py", line 723, in __call__
    return self._application(environ, start_response)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints_management/control/wsgi.py", line 415, in __call__
    result = b''.join(result)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints/endpoints_dispatcher.py", line 147, in __call__
    yield self.dispatch(request, start_response)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints/endpoints_dispatcher.py", line 170, in dispatch
    return self.call_backend(request, start_response)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints/endpoints_dispatcher.py", line 337, in call_backend
    orig_request, params, method_config)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints/endpoints_dispatcher.py", line 510, in transform_request
    request = self.transform_rest_request(orig_request, params, method_params)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints/endpoints_dispatcher.py", line 641, in transform_rest_request
    self._update_from_body(body_json, request.body_json)
  File "/base/data/home/apps/s~peeter-sandbox/20190418t084040.417569099234297404/lib/endpoints/endpoints_dispatcher.py", line 552, in _update_from_body
    for key, value in source.iteritems():
AttributeError: 'unicode' object has no attribute 'iteritems'"

For me it seems, that in the endpoints_dispatcher.py, _update_from_body functions just assumes that the given request.body_json is a dict without providing a graceful fallback.