mirror of https://github.com/pallets/flask.git
JSON response tests and first draft of code that passes
This commit is contained in:
parent
b099999c6c
commit
ca547f0ec3
|
@ -25,6 +25,14 @@ def _get_data(req, cache):
|
||||||
return req.data
|
return req.data
|
||||||
|
|
||||||
|
|
||||||
|
def _is_mimetype_json(mimetype):
|
||||||
|
if mimetype == 'application/json':
|
||||||
|
return True
|
||||||
|
if mimetype.startswith('application/') and mimetype.endswith('+json'):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
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.
|
||||||
|
@ -115,12 +123,7 @@ class Request(RequestBase):
|
||||||
|
|
||||||
.. versionadded:: 0.11
|
.. versionadded:: 0.11
|
||||||
"""
|
"""
|
||||||
mt = self.mimetype
|
return _is_mimetype_json(self.mimetype)
|
||||||
if mt == 'application/json':
|
|
||||||
return True
|
|
||||||
if mt.startswith('application/') and mt.endswith('+json'):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_json(self, force=False, silent=False, cache=True):
|
def get_json(self, force=False, silent=False, cache=True):
|
||||||
"""Parses the incoming JSON request data and returns it. By default
|
"""Parses the incoming JSON request data and returns it. By default
|
||||||
|
@ -202,3 +205,69 @@ class Response(ResponseBase):
|
||||||
set :attr:`~flask.Flask.response_class` to your subclass.
|
set :attr:`~flask.Flask.response_class` to your subclass.
|
||||||
"""
|
"""
|
||||||
default_mimetype = 'text/html'
|
default_mimetype = 'text/html'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def json(self):
|
||||||
|
"""If the mimetype is :mimetype:`application/json` this will contain the
|
||||||
|
parsed JSON data. Otherwise this will be ``None``.
|
||||||
|
|
||||||
|
The :meth:`get_json` method should be used instead.
|
||||||
|
|
||||||
|
.. versionadded:: 1.0
|
||||||
|
"""
|
||||||
|
from warnings import warn
|
||||||
|
warn(DeprecationWarning('json is deprecated. '
|
||||||
|
'Use get_json() instead.'), stacklevel=2)
|
||||||
|
return self.get_json()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_json(self):
|
||||||
|
"""Indicates if this response is JSON or not. By default a response
|
||||||
|
is considered to include JSON data if the mimetype is
|
||||||
|
:mimetype:`application/json` or :mimetype:`application/*+json`.
|
||||||
|
|
||||||
|
.. versionadded:: 1.0
|
||||||
|
"""
|
||||||
|
return _is_mimetype_json(self.mimetype)
|
||||||
|
|
||||||
|
def get_json(self, force=False, silent=False, cache=True):
|
||||||
|
"""Parses the incoming JSON request data and returns it. If
|
||||||
|
parsing fails the :meth:`on_json_loading_failed` method on the
|
||||||
|
request object will be invoked. By default this function will
|
||||||
|
only load the json data if the mimetype is :mimetype:`application/json`
|
||||||
|
but this can be overridden by the `force` parameter.
|
||||||
|
|
||||||
|
:param force: if set to ``True`` the mimetype is ignored.
|
||||||
|
:param silent: if set to ``True`` this method will fail silently
|
||||||
|
and return ``None``.
|
||||||
|
:param cache: if set to ``True`` the parsed JSON data is remembered
|
||||||
|
on the request.
|
||||||
|
|
||||||
|
.. versionadded:: 1.0
|
||||||
|
"""
|
||||||
|
rv = getattr(self, '_cached_json', _missing)
|
||||||
|
if rv is not _missing:
|
||||||
|
return rv
|
||||||
|
|
||||||
|
if not (force or self.is_json):
|
||||||
|
return None
|
||||||
|
|
||||||
|
# We accept a request charset against the specification as
|
||||||
|
# certain clients have been using this in the past. This
|
||||||
|
# fits our general approach of being nice in what we accept
|
||||||
|
# and strict in what we send out.
|
||||||
|
request_charset = self.mimetype_params.get('charset')
|
||||||
|
try:
|
||||||
|
data = _get_data(self, cache)
|
||||||
|
if request_charset is not None:
|
||||||
|
rv = json.loads(data, encoding=request_charset)
|
||||||
|
else:
|
||||||
|
rv = json.loads(data)
|
||||||
|
except ValueError as e:
|
||||||
|
if silent:
|
||||||
|
rv = None
|
||||||
|
else:
|
||||||
|
rv = self.on_json_loading_failed(e)
|
||||||
|
if cache:
|
||||||
|
self._cached_json = rv
|
||||||
|
return rv
|
||||||
|
|
|
@ -13,6 +13,7 @@ import pytest
|
||||||
import flask
|
import flask
|
||||||
|
|
||||||
from flask._compat import text_type
|
from flask._compat import text_type
|
||||||
|
from flask.json import jsonify
|
||||||
|
|
||||||
|
|
||||||
def test_environ_defaults_from_config():
|
def test_environ_defaults_from_config():
|
||||||
|
@ -203,21 +204,27 @@ def test_full_url_request():
|
||||||
assert 'gin' in flask.request.form
|
assert 'gin' in flask.request.form
|
||||||
assert 'vodka' in flask.request.args
|
assert 'vodka' in flask.request.args
|
||||||
|
|
||||||
def test_json_request():
|
def test_json_request_and_response():
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
app.testing = True
|
app.testing = True
|
||||||
|
|
||||||
@app.route('/api', methods=['POST'])
|
@app.route('/echo', methods=['POST'])
|
||||||
def api():
|
def echo():
|
||||||
return ''
|
return jsonify(flask.request.json)
|
||||||
|
|
||||||
with app.test_client() as c:
|
with app.test_client() as c:
|
||||||
json_data = {'drink': {'gin': 1, 'tonic': True}, 'price': 10}
|
json_data = {'drink': {'gin': 1, 'tonic': True}, 'price': 10}
|
||||||
rv = c.post('/api', json=json_data)
|
rv = c.post('/echo', json=json_data)
|
||||||
assert rv.status_code == 200
|
|
||||||
|
# Request should be in JSON
|
||||||
assert flask.request.is_json
|
assert flask.request.is_json
|
||||||
assert flask.request.get_json() == json_data
|
assert flask.request.get_json() == json_data
|
||||||
|
|
||||||
|
# Response should be in JSON
|
||||||
|
assert rv.status_code == 200
|
||||||
|
assert rv.is_json
|
||||||
|
assert rv.get_json() == json_data
|
||||||
|
|
||||||
def test_subdomain():
|
def test_subdomain():
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
app.config['SERVER_NAME'] = 'example.com'
|
app.config['SERVER_NAME'] = 'example.com'
|
||||||
|
|
Loading…
Reference in New Issue