Imply the |safe on tojson in templates and change escaping logic
This commit is contained in:
parent
56d3b74488
commit
ef72b78042
7 changed files with 46 additions and 31 deletions
2
CHANGES
2
CHANGES
|
|
@ -17,6 +17,8 @@ Release date to be decided.
|
||||||
``template_filter`` method family.
|
``template_filter`` method family.
|
||||||
- Set the content-length header for x-sendfile.
|
- Set the content-length header for x-sendfile.
|
||||||
- ``tojson`` filter now does not escape script blocks in HTML5 parsers.
|
- ``tojson`` filter now does not escape script blocks in HTML5 parsers.
|
||||||
|
- ``tojson`` used in templates is now safe by default due. This was
|
||||||
|
allowed due to the different escaping behavior.
|
||||||
- Flask will now raise an error if you attempt to register a new function
|
- Flask will now raise an error if you attempt to register a new function
|
||||||
on an already used endpoint.
|
on an already used endpoint.
|
||||||
- Added wrapper module around simplejson and added default serialization
|
- Added wrapper module around simplejson and added default serialization
|
||||||
|
|
|
||||||
|
|
@ -364,7 +364,8 @@ JSON module:
|
||||||
The :func:`~htmlsafe_dumps` function of this json module is also available
|
The :func:`~htmlsafe_dumps` function of this json module is also available
|
||||||
as filter called ``|tojson`` in Jinja2. Note that inside `script`
|
as filter called ``|tojson`` in Jinja2. Note that inside `script`
|
||||||
tags no escaping must take place, so make sure to disable escaping
|
tags no escaping must take place, so make sure to disable escaping
|
||||||
with ``|safe`` if you intend to use it inside `script` tags:
|
with ``|safe`` if you intend to use it inside `script` tags unless
|
||||||
|
you are using Flask 0.10 which implies that:
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
.. sourcecode:: html+jinja
|
||||||
|
|
||||||
|
|
@ -372,8 +373,6 @@ with ``|safe`` if you intend to use it inside `script` tags:
|
||||||
doSomethingWith({{ user.username|tojson|safe }});
|
doSomethingWith({{ user.username|tojson|safe }});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
Note that the ``|tojson`` filter escapes forward slashes properly.
|
|
||||||
|
|
||||||
.. autofunction:: jsonify
|
.. autofunction:: jsonify
|
||||||
|
|
||||||
.. autofunction:: dumps
|
.. autofunction:: dumps
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,10 @@ like this:
|
||||||
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
|
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
The ``|safe`` is necessary so that Jinja does not escape the JSON encoded
|
The ``|safe`` is necessary in Flask before 0.10 so that Jinja does not
|
||||||
string with HTML rules. Usually this would be necessary, but we are
|
escape the JSON encoded string with HTML rules. Usually this would be
|
||||||
inside a `script` block here where different rules apply.
|
necessary, but we are inside a `script` block here where different rules
|
||||||
|
apply.
|
||||||
|
|
||||||
.. admonition:: Information for Pros
|
.. admonition:: Information for Pros
|
||||||
|
|
||||||
|
|
@ -76,6 +77,10 @@ inside a `script` block here where different rules apply.
|
||||||
escape slashes for you (``{{ "</script>"|tojson|safe }}`` is rendered as
|
escape slashes for you (``{{ "</script>"|tojson|safe }}`` is rendered as
|
||||||
``"<\/script>"``).
|
``"<\/script>"``).
|
||||||
|
|
||||||
|
In Flask 0.10 it goes a step further and escapes all HTML tags with
|
||||||
|
unicode escapes. This makes it possible for Flask to automatically
|
||||||
|
mark the result as HTML safe.
|
||||||
|
|
||||||
|
|
||||||
JSON View Functions
|
JSON View Functions
|
||||||
-------------------
|
-------------------
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,8 @@ by Jinja2 itself:
|
||||||
fly.
|
fly.
|
||||||
|
|
||||||
Note that inside `script` tags no escaping must take place, so make
|
Note that inside `script` tags no escaping must take place, so make
|
||||||
sure to disable escaping with ``|safe`` if you intend to use it inside
|
sure to disable escaping with ``|safe`` before Flask 0.10 if you intend
|
||||||
`script` tags:
|
to use it inside `script` tags:
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
.. sourcecode:: html+jinja
|
||||||
|
|
||||||
|
|
@ -115,8 +115,6 @@ by Jinja2 itself:
|
||||||
doSomethingWith({{ user.username|tojson|safe }});
|
doSomethingWith({{ user.username|tojson|safe }});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
That the ``|tojson`` filter escapes forward slashes properly for you.
|
|
||||||
|
|
||||||
Controlling Autoescaping
|
Controlling Autoescaping
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -659,7 +659,7 @@ class Flask(_PackageBoundObject):
|
||||||
session=session,
|
session=session,
|
||||||
g=g
|
g=g
|
||||||
)
|
)
|
||||||
rv.filters['tojson'] = json.htmlsafe_dumps
|
rv.filters['tojson'] = json.tojson_filter
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
def create_global_jinja_loader(self):
|
def create_global_jinja_loader(self):
|
||||||
|
|
@ -1707,13 +1707,6 @@ class Flask(_PackageBoundObject):
|
||||||
rv = func(exc)
|
rv = func(exc)
|
||||||
request_tearing_down.send(self, exc=exc)
|
request_tearing_down.send(self, exc=exc)
|
||||||
|
|
||||||
# If this interpreter supports clearing the exception information
|
|
||||||
# we do that now. This will only go into effect on Python 2.x,
|
|
||||||
# on 3.x it disappears automatically at the end of the exception
|
|
||||||
# stack.
|
|
||||||
if hasattr(sys, 'exc_clear'):
|
|
||||||
sys.exc_clear()
|
|
||||||
|
|
||||||
def do_teardown_appcontext(self, exc=None):
|
def do_teardown_appcontext(self, exc=None):
|
||||||
"""Called when an application context is popped. This works pretty
|
"""Called when an application context is popped. This works pretty
|
||||||
much the same as :meth:`do_teardown_request` but for the application
|
much the same as :meth:`do_teardown_request` but for the application
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ from .globals import current_app, request
|
||||||
from ._compat import text_type, PY2
|
from ._compat import text_type, PY2
|
||||||
|
|
||||||
from werkzeug.http import http_date
|
from werkzeug.http import http_date
|
||||||
|
from jinja2 import Markup
|
||||||
|
|
||||||
# Use the same json implementation as itsdangerous on which we
|
# Use the same json implementation as itsdangerous on which we
|
||||||
# depend anyways.
|
# depend anyways.
|
||||||
|
|
@ -160,18 +161,26 @@ def load(fp, **kwargs):
|
||||||
def htmlsafe_dumps(obj, **kwargs):
|
def htmlsafe_dumps(obj, **kwargs):
|
||||||
"""Works exactly like :func:`dumps` but is safe for use in ``<script>``
|
"""Works exactly like :func:`dumps` but is safe for use in ``<script>``
|
||||||
tags. It accepts the same arguments and returns a JSON string. Note that
|
tags. It accepts the same arguments and returns a JSON string. Note that
|
||||||
this is available in templates through the ``|tojson`` filter but it will
|
this is available in templates through the ``|tojson`` filter which will
|
||||||
have to be wrapped in ``|safe`` unless **true** XHTML is being used.
|
also mark the result as safe. Due to how this function escapes certain
|
||||||
|
characters this is safe even if used outside of ``<script>`` tags.
|
||||||
|
|
||||||
|
.. versionchanged:: 0.10
|
||||||
|
This function's return value is now always safe for HTML usage, even
|
||||||
|
if outside of script tags or if used in XHTML.
|
||||||
"""
|
"""
|
||||||
rv = dumps(obj, **kwargs)
|
rv = dumps(obj, **kwargs) \
|
||||||
if _slash_escape:
|
.replace(u'<', u'\\u003c') \
|
||||||
rv = rv.replace('/', '\\/')
|
.replace(u'>', u'\\u003e') \
|
||||||
return rv.replace('<!', '<\\u0021')
|
.replace(u'&', u'\\u0026')
|
||||||
|
if not _slash_escape:
|
||||||
|
rv = rv.replace('\\/', '/')
|
||||||
|
return rv
|
||||||
|
|
||||||
|
|
||||||
def htmlsafe_dump(obj, fp, **kwargs):
|
def htmlsafe_dump(obj, fp, **kwargs):
|
||||||
"""Like :func:`htmlsafe_dumps` but writes into a file object."""
|
"""Like :func:`htmlsafe_dumps` but writes into a file object."""
|
||||||
fp.write(htmlsafe_dumps(obj, **kwargs))
|
fp.write(unicode(htmlsafe_dumps(obj, **kwargs)))
|
||||||
|
|
||||||
|
|
||||||
def jsonify(*args, **kwargs):
|
def jsonify(*args, **kwargs):
|
||||||
|
|
@ -213,3 +222,7 @@ def jsonify(*args, **kwargs):
|
||||||
return current_app.response_class(dumps(dict(*args, **kwargs),
|
return current_app.response_class(dumps(dict(*args, **kwargs),
|
||||||
indent=indent),
|
indent=indent),
|
||||||
mimetype='application/json')
|
mimetype='application/json')
|
||||||
|
|
||||||
|
|
||||||
|
def tojson_filter(obj, **kwargs):
|
||||||
|
return Markup(htmlsafe_dumps(obj, **kwargs))
|
||||||
|
|
|
||||||
|
|
@ -92,12 +92,17 @@ class JSONTestCase(FlaskTestCase):
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
render = flask.render_template_string
|
render = flask.render_template_string
|
||||||
with app.test_request_context():
|
with app.test_request_context():
|
||||||
rv = render('{{ "</script>"|tojson|safe }}')
|
rv = flask.json.htmlsafe_dumps('</script>')
|
||||||
self.assert_equal(rv, '"<\\/script>"')
|
self.assert_equal(rv, u'"\\u003c/script\\u003e"')
|
||||||
rv = render('{{ "<\0/script>"|tojson|safe }}')
|
self.assert_equal(type(rv), text_type)
|
||||||
self.assert_equal(rv, '"<\\u0000\\/script>"')
|
rv = render('{{ "</script>"|tojson }}')
|
||||||
rv = render('{{ "<!--<script>"|tojson|safe }}')
|
self.assert_equal(rv, '"\\u003c/script\\u003e"')
|
||||||
self.assert_equal(rv, '"<\\u0021--<script>"')
|
rv = render('{{ "<\0/script>"|tojson }}')
|
||||||
|
self.assert_equal(rv, '"\\u003c\\u0000/script\\u003e"')
|
||||||
|
rv = render('{{ "<!--<script>"|tojson }}')
|
||||||
|
self.assert_equal(rv, '"\\u003c!--\\u003cscript\\u003e"')
|
||||||
|
rv = render('{{ "&"|tojson }}')
|
||||||
|
self.assert_equal(rv, '"\\u0026"')
|
||||||
|
|
||||||
def test_json_customization(self):
|
def test_json_customization(self):
|
||||||
class X(object):
|
class X(object):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue