Skip to content

Commit

Permalink
feat(response): prefer falcon.MEDIA_* constants to stdlib's `mimety…
Browse files Browse the repository at this point in the history
…pes`
  • Loading branch information
vytas7 committed Jun 3, 2023
1 parent a7f7008 commit 59917dc
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 6 deletions.
6 changes: 6 additions & 0 deletions docs/_newsfragments/2110.newandimproved.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Following the recommendation from
`RFC 9239 <https://www.rfc-editor.org/rfc/rfc9239>`__, the
:ref:`MEDIA_JS <media_type_constants>` constant has been updated to
``text/javascript``. Furthermore, this and other media type constants are now
preferred to the stdlib's :mod:`mimetypes` for the initialization of
:attr:`~falcon.ResponseOptions.static_media_types`.
28 changes: 25 additions & 3 deletions falcon/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@
# contrary to the RFCs.
MEDIA_XML = 'application/xml'

# NOTE: According to RFC 9239, Changed the intended usage of the
# media type "text/javascript" from OBSOLETE to COMMON. Changed
# the intended usage for all other script media types to obsolete.
# NOTE(euj1n0ng): According to RFC 9239, Changed the intended usage of the
# media type "text/javascript" from OBSOLETE to COMMON. Changed
# the intended usage for all other script media types to obsolete.
MEDIA_JS = 'text/javascript'

# NOTE(kgriffs): According to RFC 6838, most text media types should
Expand Down Expand Up @@ -137,6 +137,28 @@
]
)

# NOTE(vytas): We strip the preferred charsets from the default static file
# type mapping as it is hard to make any assumptions without knowing which
# files are going to be served. Moreover, the popular web servers (like
# Nginx) do not try to guess either.
_DEFAULT_STATIC_MEDIA_TYPES = tuple(
(ext, media_type.split(';', 1)[0])
for ext, media_type in (
('.bmp', MEDIA_BMP),
('.gif', MEDIA_GIF),
('.htm', MEDIA_HTML),
('.html', MEDIA_HTML),
('.jpeg', MEDIA_JPEG),
('.jpg', MEDIA_JPEG),
('.js', MEDIA_JS),
('.png', MEDIA_PNG),
('.txt', MEDIA_TEXT),
('.xml', MEDIA_XML),
('.yaml', MEDIA_YAML),
('.yml', MEDIA_YAML),
)
)

# NOTE(kgriffs): Special singleton to be used internally whenever using
# None would be ambiguous.
_UNSET = object()
Expand Down
4 changes: 3 additions & 1 deletion falcon/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import functools
import mimetypes

from falcon.constants import _DEFAULT_STATIC_MEDIA_TYPES
from falcon.constants import _UNSET
from falcon.constants import DEFAULT_MEDIA_TYPE
from falcon.errors import HeaderNotSupported
Expand Down Expand Up @@ -1246,4 +1247,5 @@ def __init__(self):

if not mimetypes.inited:
mimetypes.init()
self.static_media_types = mimetypes.types_map
self.static_media_types = mimetypes.types_map.copy()
self.static_media_types.update(_DEFAULT_STATIC_MEDIA_TYPES)
5 changes: 3 additions & 2 deletions tests/test_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,14 @@ def test_response_removed_stream_len(resp):
def test_response_option_mimetype_init(monkeypatch):
mock = MagicMock()
mock.inited = False
mock.types_map = {'.js': 'application/javascript'}
monkeypatch.setattr('falcon.response.mimetypes', mock)

ro = ResponseOptions()

assert ro.static_media_types is mock.types_map
assert ro.static_media_types['.js'] == 'text/javascript'

mock.reset_mock()
mock.inited = True
ro = ResponseOptions()
assert ro.static_media_types is mock.types_map
mock.init.assert_not_called()

0 comments on commit 59917dc

Please sign in to comment.