Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/1.0-maintenance'
Browse files Browse the repository at this point in the history
  • Loading branch information
davidism committed Jan 7, 2019
2 parents 4f32c6d + ded7cbe commit a74864e
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 4 deletions.
11 changes: 10 additions & 1 deletion CHANGES.rst
Expand Up @@ -36,13 +36,22 @@ Unreleased
(ISO-8859-1). This fixes compatibility with Gunicorn, which is
stricter about header encodings than PEP 3333. (`#2766`_)
- Allow custom CLIs using ``FlaskGroup`` to set the debug flag without
it always being overwritten based on environment variables. (`#2765`_)
it always being overwritten based on environment variables.
(`#2765`_)
- ``flask --version`` outputs Werkzeug's version and simplifies the
Python version. (`#2825`_)
- :func:`send_file` handles an ``attachment_filename`` that is a
native Python 2 string (bytes) with UTF-8 coded bytes. (`#2933`_)
- A catch-all error handler registered for ``HTTPException`` will not
handle ``RoutingExcpetion``, which is used internally during
routing. This fixes the unexpected behavior that had been introduced
in 1.0. (`#2986`_)

.. _#2766: https://github.com/pallets/flask/issues/2766
.. _#2765: https://github.com/pallets/flask/pull/2765
.. _#2825: https://github.com/pallets/flask/pull/2825
.. _#2933: https://github.com/pallets/flask/issues/2933
.. _#2986: https://github.com/pallets/flask/pull/2986


Version 1.0.2
Expand Down
19 changes: 18 additions & 1 deletion flask/app.py
Expand Up @@ -20,7 +20,8 @@
from werkzeug.datastructures import Headers, ImmutableDict
from werkzeug.exceptions import BadRequest, BadRequestKeyError, HTTPException, \
InternalServerError, MethodNotAllowed, default_exceptions
from werkzeug.routing import BuildError, Map, RequestRedirect, Rule
from werkzeug.routing import BuildError, Map, RequestRedirect, \
RoutingException, Rule

from . import cli, json
from ._compat import integer_types, reraise, string_types, text_type
Expand Down Expand Up @@ -1631,13 +1632,29 @@ def handle_http_exception(self, e):
registered error handlers and fall back to returning the
exception as response.
.. versionchanged:: 1.0.3
``RoutingException``, used internally for actions such as
slash redirects during routing, is not passed to error
handlers.
.. versionchanged:: 1.0
Exceptions are looked up by code *and* by MRO, so
``HTTPExcpetion`` subclasses can be handled with a catch-all
handler for the base ``HTTPException``.
.. versionadded:: 0.3
"""
# Proxy exceptions don't have error codes. We want to always return
# those unchanged as errors
if e.code is None:
return e

# RoutingExceptions are used internally to trigger routing
# actions, such as slash redirects raising RequestRedirect. They
# are not raised or handled in user code.
if isinstance(e, RoutingException):
return e

handler = self._find_error_handler(e)
if handler is None:
return e
Expand Down
3 changes: 3 additions & 0 deletions flask/helpers.py
Expand Up @@ -577,6 +577,9 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
raise TypeError('filename unavailable, required for '
'sending as attachment')

if not isinstance(attachment_filename, text_type):
attachment_filename = attachment_filename.decode('utf-8')

try:
attachment_filename = attachment_filename.encode('ascii')
except UnicodeEncodeError:
Expand Down
2 changes: 2 additions & 0 deletions tests/test_helpers.py
Expand Up @@ -680,6 +680,8 @@ def test_attachment(self, app, req_ctx):
(u'Ñandú/pingüino.txt', '"Nandu/pinguino.txt"',
'%C3%91and%C3%BA%EF%BC%8Fping%C3%BCino.txt'),
(u'Vögel.txt', 'Vogel.txt', 'V%C3%B6gel.txt'),
# Native string not marked as Unicode on Python 2
('tést.txt', 'test.txt', 't%C3%A9st.txt'),
))
def test_attachment_filename_encoding(self, filename, ascii, utf8):
rv = flask.send_file('static/index.html', as_attachment=True, attachment_filename=filename)
Expand Down
8 changes: 6 additions & 2 deletions tests/test_user_error_handler.py
Expand Up @@ -184,12 +184,16 @@ def catchall_errorhandler(e):
def forbidden():
raise Forbidden()

@app.route("/slash/")
def slash():
return "slash"

app.register_blueprint(bp, url_prefix='/bp')

c = app.test_client()
assert c.get('/bp/undefined').data == b'bp-default'
assert c.get('/bp/forbidden').data == b'bp-forbidden'
assert c.get('/undefined').data == b'default'
assert c.get('/forbidden').data == b'forbidden'


# Don't handle RequestRedirect raised when adding slash.
assert c.get("/slash", follow_redirects=True).data == b"slash"

0 comments on commit a74864e

Please sign in to comment.