Browse Source

On JSON requests, the JSON response should have Content-Type: application/json and the body of the response should be a JSON object.

pull/423/head
Jeffrey Finkelstein 13 years ago
parent
commit
9711fd4020
  1. 2
      CHANGES
  2. 12
      flask/testsuite/helpers.py
  3. 56
      flask/wrappers.py

2
CHANGES

@ -8,6 +8,8 @@ Version 0.9
Relase date to be decided, codename to be chosen. Relase date to be decided, codename to be chosen.
- The :func:`flask.Request.on_json_loading_failed` now returns a JSON formatted
response by default.
- The :func:`flask.url_for` function now can generate anchors to the - The :func:`flask.url_for` function now can generate anchors to the
generated links. generated links.
- The :func:`flask.url_for` function now can also explicitly generate - The :func:`flask.url_for` function now can also explicitly generate

12
flask/testsuite/helpers.py

@ -40,6 +40,18 @@ class JSONTestCase(FlaskTestCase):
rv = c.post('/json', data='malformed', content_type='application/json') rv = c.post('/json', data='malformed', content_type='application/json')
self.assert_equal(rv.status_code, 400) self.assert_equal(rv.status_code, 400)
def test_json_bad_requests_content_type(self):
app = flask.Flask(__name__)
@app.route('/json', methods=['POST'])
def return_json():
return unicode(flask.request.json)
c = app.test_client()
rv = c.post('/json', data='malformed', content_type='application/json')
self.assert_equal(rv.status_code, 400)
self.assert_equal(rv.mimetype, 'application/json')
self.assert_('description' in flask.json.loads(rv.data))
self.assert_('<p>' not in flask.json.loads(rv.data)['description'])
def test_json_body_encoding(self): def test_json_body_encoding(self):
app = flask.Flask(__name__) app = flask.Flask(__name__)
app.testing = True app.testing = True

56
flask/wrappers.py

@ -10,7 +10,7 @@
""" """
from werkzeug.wrappers import Request as RequestBase, Response as ResponseBase from werkzeug.wrappers import Request as RequestBase, Response as ResponseBase
from werkzeug.exceptions import BadRequest from werkzeug.exceptions import BadRequest, HTTPException
from werkzeug.utils import cached_property from werkzeug.utils import cached_property
from .debughelpers import attach_enctype_error_multidict from .debughelpers import attach_enctype_error_multidict
@ -18,6 +18,43 @@ from .helpers import json, _assert_have_json
from .globals import _request_ctx_stack from .globals import _request_ctx_stack
class JSONHTTPException(HTTPException):
"""A base class for HTTP exceptions with ``Content-Type:
application/json``.
The ``description`` attribute of this class must set to a string (*not* an
HTML string) which describes the error.
"""
def get_body(self, environ):
"""Overrides :meth:`werkzeug.exceptions.HTTPException.get_body` to
return the description of this error in JSON format instead of HTML.
"""
return json.dumps(dict(description=self.get_description(environ)))
def get_headers(self, environ):
"""Returns a list of headers including ``Content-Type:
application/json``.
"""
return [('Content-Type', 'application/json')]
class JSONBadRequest(JSONHTTPException, BadRequest):
"""Represents an HTTP ``400 Bad Request`` error whose body contains an
error message in JSON format instead of HTML format (as in the superclass).
"""
#: The description of the error which occurred as a string.
description = (
'The browser (or proxy) sent a request that this server could not '
'understand.'
)
class Request(RequestBase): class Request(RequestBase):
"""The request object used by default in Flask. Remembers the """The request object used by default in Flask. Remembers the
matched endpoint and view arguments. matched endpoint and view arguments.
@ -108,12 +145,23 @@ class Request(RequestBase):
def on_json_loading_failed(self, e): def on_json_loading_failed(self, e):
"""Called if decoding of the JSON data failed. The return value of """Called if decoding of the JSON data failed. The return value of
this method is used by :attr:`json` when an error ocurred. The this method is used by :attr:`json` when an error ocurred. The default
default implementation raises a :class:`~werkzeug.exceptions.BadRequest`. implementation raises a :class:`JSONBadRequest`, which is a subclass of
:class:`~werkzeug.exceptions.BadRequest` which sets the
``Content-Type`` to ``application/json`` and provides a JSON-formatted
error description::
{"description": "The browser (or proxy) sent a request that \
this server could not understand."}
.. versionchanged:: 0.9
Return a :class:`JSONBadRequest` instead of a
:class:`~werkzeug.exceptions.BadRequest` by default.
.. versionadded:: 0.8 .. versionadded:: 0.8
""" """
raise BadRequest() raise JSONBadRequest()
def _load_form_data(self): def _load_form_data(self):
RequestBase._load_form_data(self) RequestBase._load_form_data(self)

Loading…
Cancel
Save