codecov[bot]: # [Codecov](https://codecov.io/gh/falconry/falcon/pull/1226?src=pr&el=h1) Report
> Merging [#1226](https://codecov.io/gh/falconry/falcon/pull/1226?src=pr&el=desc) into [master](https://codecov.io/gh/falconry/falcon/commit/800396f0a8d9d13889386522c4bee3e4661d547f?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/falconry/falcon/pull/1226/graphs/tree.svg?height=150&src=pr&token=zOtkfNQ3h6&width=650)](https://codecov.io/gh/falconry/falcon/pull/1226?src=pr&el=tree)

```diff
@@          Coverage Diff           @@
##           master   #1226   +/-   ##
======================================
  Coverage     100%    100%           
======================================
  Files          38      38           
  Lines        2484    2491    +7     
  Branches      364     367    +3     
======================================
+ Hits         2484    2491    +7
```


| [Impacted Files](https://codecov.io/gh/falconry/falcon/pull/1226?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [falcon/routing/static.py](https://codecov.io/gh/falconry/falcon/pull/1226/diff?src=pr&el=tree#diff-ZmFsY29uL3JvdXRpbmcvc3RhdGljLnB5) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/falconry/falcon/pull/1226?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/falconry/falcon/pull/1226?src=pr&el=footer). Last update [800396f...d77e0ec](https://codecov.io/gh/falconry/falcon/pull/1226?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

CaselIT: I should've addressed the comments.
diff --git a/falcon/api.py b/falcon/api.py
index c1ef8fa..65e0d76 100644
--- a/falcon/api.py
+++ b/falcon/api.py
@@ -371,7 +371,7 @@ class API(object):
         self._router.add_route(uri_template, method_map, resource, *args,
                                **kwargs)
 
-    def add_static_route(self, prefix, directory, downloadable=False):
+    def add_static_route(self, prefix, directory, downloadable=False, fallback_filename=None):
         """Add a route to a directory of static files.
 
         Static routes provide a way to serve files directly. This
@@ -383,6 +383,8 @@ class API(object):
             Serving files directly from the web server,
             rather than through the Python app, will always be more efficient,
             and therefore should be preferred in production deployments.
+            For security reasons, the directory and the fallback_filename (if provided)
+            should be read only for the account running the application.
 
         Static routes are matched in LIFO order. Therefore, if the same
         prefix is used for two routes, the second one will override the
@@ -410,12 +412,16 @@ class API(object):
             downloadable (bool): Set to ``True`` to include a
                 Content-Disposition header in the response. The "filename"
                 directive is simply set to the name of the requested file.
+            fallback_filename (str): Fallback filename used when the requested file
+                is not found. Can be a relative path inside the prefix folder or any valid
+                absolute path.
 
         """
 
         self._static_routes.insert(
             0,
-            routing.StaticRoute(prefix, directory, downloadable=downloadable)
+            routing.StaticRoute(prefix, directory, downloadable=downloadable,
+                                fallback_filename=fallback_filename)
         )
 
     def add_sink(self, sink, prefix=r'/'):
diff --git a/falcon/routing/static.py b/falcon/routing/static.py
index ba3fab2..d659f99 100644
--- a/falcon/routing/static.py
+++ b/falcon/routing/static.py
@@ -24,6 +24,9 @@ class StaticRoute(object):
         downloadable (bool): Set to ``True`` to include a
             Content-Disposition header in the response. The "filename"
             directive is simply set to the name of the requested file.
+        fallback_filename (str): Fallback filename used when the requested file
+                is not found. Can be a relative path inside the prefix folder or any valid
+                absolute path.
     """
 
     # NOTE(kgriffs): Don't allow control characters and reserved chars
@@ -33,13 +36,20 @@ class StaticRoute(object):
     # minimizes how much can be included in the payload.
     _MAX_NON_PREFIXED_LEN = 512
 
-    def __init__(self, prefix, directory, downloadable=False):
+    def __init__(self, prefix, directory, downloadable=False, fallback_filename=None):
         if not prefix.startswith('/'):
             raise ValueError("prefix must start with '/'")
 
         if not os.path.isabs(directory):
             raise ValueError('directory must be an absolute path')
 
+        if fallback_filename is None:
+            self._fallback_filename = None
+        else:
+            self._fallback_filename = os.path.join(directory, fallback_filename)
+            if not os.path.isfile(self._fallback_filename):
+                raise ValueError('fallback_filename is not a file')
+
         # NOTE(kgriffs): Ensure it ends with a path separator to ensure
         # we only match on the complete segment. Don't raise an error
         # because most people won't expect to have to append a slash.
@@ -52,7 +62,9 @@ class StaticRoute(object):
 
     def match(self, path):
         """Check whether the given path matches this route."""
-        return path.startswith(self._prefix)
+        if self._fallback_filename is None:
+            return path.startswith(self._prefix)
+        return path.startswith(self._prefix) or path == self._prefix[:-1]
 
     def __call__(self, req, resp):
         """Resource responder for this route."""
@@ -61,7 +73,8 @@ class StaticRoute(object):
 
         # NOTE(kgriffs): Check surrounding whitespace and strip trailing
         # periods, which are illegal on windows
-        if (not without_prefix or
+        # NOTE(CaselIT): An empty filename is allowed when fallback_filename is provided
+        if (not (without_prefix or self._fallback_filename is not None) or
                 without_prefix.strip().rstrip('.') != without_prefix or
                 self._DISALLOWED_CHARS_PATTERN.search(without_prefix) or
                 '\\' in without_prefix or
@@ -86,7 +99,12 @@ class StaticRoute(object):
         try:
             resp.stream = io.open(file_path, 'rb')
         except IOError:
-            raise falcon.HTTPNotFound()
+            if self._fallback_filename is None:
+                raise falcon.HTTPNotFound()
+            try:
+                resp.stream = io.open(self._fallback_filename, 'rb')
+            except IOError:
+                raise falcon.HTTPNotFound()
 
         suffix = os.path.splitext(file_path)[1]
         resp.content_type = resp.options.static_media_types.get(

Add default file name in the StaticRoute 
Consider adding the ability to specify a default filename for a static route. 

I'm not sure if it would be best to send the file or raise an `HTTPMovedPermanently` (or a `HTTPPermanentRedirect`). 
Probably for performance reasons the redirect would be best (but in this case maybe `default_filename` should become `default_location`)


diff --git a/tests/test_static.py b/tests/test_static.py
index 2fbb55c..b92d978 100644
--- a/tests/test_static.py
+++ b/tests/test_static.py
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 
 import io
+import os
 
 import pytest
 
@@ -106,6 +107,21 @@ def test_invalid_args(prefix, directory, client):
         client.app.add_static_route(prefix, directory)
 
 
+@pytest.mark.parametrize('default', [
+    'not-existing-file',
+    # directories
+    '.',
+    '/tmp',
+])
+def test_invalid_args_fallback_filename(client, default):
+    prefix, directory = '/static', '/var/www/statics'
+    with pytest.raises(ValueError, match='fallback_filename'):
+        StaticRoute(prefix, directory, fallback_filename=default)
+
+    with pytest.raises(ValueError, match='fallback_filename'):
+        client.app.add_static_route(prefix, directory, fallback_filename=default)
+
+
 @pytest.mark.parametrize('uri_prefix, uri_path, expected_path, mtype', [
     ('/static/', '/css/test.css', '/css/test.css', 'text/css'),
     ('/static', '/css/test.css', '/css/test.css', 'text/css'),
@@ -199,3 +215,88 @@ def test_downloadable_not_found(client):
 
     response = client.simulate_request(path='/downloads/thing.zip')
     assert response.status == falcon.HTTP_404
+
+
+@pytest.mark.parametrize('uri, default, expected', [
+    ('', 'default', 'default'),
+    ('other', 'default', 'default'),
+    ('index2', 'index', 'index2'),
+    ('absolute', '/foo/bar/index', '/foo/bar/index'),
+])
+def test_fallback_filename(uri, default, expected, monkeypatch):
+
+    def mockOpen(path, mode):
+        if default in path:
+            return path
+        raise IOError()
+
+    monkeypatch.setattr(io, 'open', mockOpen)
+    monkeypatch.setattr('os.path.isfile', lambda file: default in file)
+
+    sr = StaticRoute('/static', '/var/www/statics', fallback_filename=default)
+
+    req_path = '/static/' + uri
+
+    req = Request(testing.create_environ(
+        host='test.com',
+        path=req_path,
+        app='statics'
+    ))
+    resp = Response()
+    sr(req, resp)
+
+    assert sr.match(req.path)
+    assert resp.stream == os.path.join('/var/www/statics', expected)
+
+
+@pytest.mark.parametrize('strip_slash', [True, False])
+@pytest.mark.parametrize('path, fallback, static_exp, assert_axp', [
+    ('/index', 'index.html', 'index', 'index'),
+    ('', 'index.html', 'index.html', None),
+    ('/', 'index.html', 'index.html', None),
+    ('/other', 'index.html', 'index.html', None),
+    ('/other', 'index.raise', None, None)
+])
+def test_e2e_fallback_filename(client, monkeypatch, strip_slash, path, fallback,
+                               static_exp, assert_axp):
+
+    def mockOpen(path, mode):
+        if 'index' in path and 'raise' not in path:
+            return [path.encode('utf-8')]
+        raise IOError()
+
+    monkeypatch.setattr(io, 'open', mockOpen)
+    monkeypatch.setattr('os.path.isfile', lambda file: 'index' in file)
+
+    client.app.req_options.strip_url_path_trailing_slash = strip_slash
+    client.app.add_static_route('/static', '/opt/somesite/static',
+                                fallback_filename=fallback)
+    client.app.add_static_route('/assets/', '/opt/somesite/assets')
+
+    def test(prefix, directory, expected):
+        response = client.simulate_request(path=prefix + path)
+        if expected is None:
+            assert response.status == falcon.HTTP_404
+        else:
+            assert response.status == falcon.HTTP_200
+            assert response.text == directory + expected
+
+    test('/static', '/opt/somesite/static/', static_exp)
+    test('/assets', '/opt/somesite/assets/', assert_axp)
+
+
+@pytest.mark.parametrize('default, path, expected', [
+    (None, '/static', False),
+    (None, '/static/', True),
+    (None, '/staticfoo', False),
+    (None, '/static/foo', True),
+    ('index2', '/static', True),
+    ('index2', '/static/', True),
+    ('index2', '/staticfoo', False),
+    ('index2', '/static/foo', True),
+])
+def test_match(default, path, expected, monkeypatch):
+    monkeypatch.setattr('os.path.isfile', lambda file: True)
+    sr = StaticRoute('/static', '/var/www/statics', fallback_filename=default)
+
+    assert sr.match(path) == expected

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.6
requirements/tests
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
certifi==2021.5.30
charset-normalizer==2.0.12
coverage==6.2
-e git+https://github.com/falconry/falcon.git@76b15bb05daae4aeab5c75307386d3b0394fde42#egg=falcon
fixtures==4.0.1
idna==3.10
importlib-metadata==4.8.3
iniconfig==1.1.1
msgpack==1.0.5
packaging==21.3
pbr==6.1.1
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
python-mimeparse==1.6.0
PyYAML==6.0.1
requests==2.27.1
six==1.17.0
testtools==2.6.0
tomli==1.2.3
typing_extensions==4.1.1
urllib3==1.26.20
zipp==3.6.0

name: falcon
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - charset-normalizer==2.0.12
      - coverage==6.2
      - fixtures==4.0.1
      - idna==3.10
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - msgpack==1.0.5
      - packaging==21.3
      - pbr==6.1.1
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-mimeparse==1.6.0
      - pyyaml==6.0.1
      - requests==2.27.1
      - six==1.17.0
      - testtools==2.6.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - zipp==3.6.0
prefix: /opt/conda/envs/falcon

tests/test_static.py::test_invalid_args_fallback_filename[not-existing-file] tests/test_static.py::test_invalid_args_fallback_filename[.] tests/test_static.py::test_invalid_args_fallback_filename[/tmp] tests/test_static.py::test_fallback_filename[-default-default] tests/test_static.py::test_fallback_filename[other-default-default] tests/test_static.py::test_fallback_filename[index2-index-index2] tests/test_static.py::test_fallback_filename[absolute-/foo/bar/index-/foo/bar/index] tests/test_static.py::test_e2e_fallback_filename[/index-index.html-index-index-True] tests/test_static.py::test_e2e_fallback_filename[/index-index.html-index-index-False] tests/test_static.py::test_e2e_fallback_filename[-index.html-index.html-None-True] tests/test_static.py::test_e2e_fallback_filename[-index.html-index.html-None-False] tests/test_static.py::test_e2e_fallback_filename[/-index.html-index.html-None-True] tests/test_static.py::test_e2e_fallback_filename[/-index.html-index.html-None-False] tests/test_static.py::test_e2e_fallback_filename[/other-index.html-index.html-None-True] tests/test_static.py::test_e2e_fallback_filename[/other-index.html-index.html-None-False] tests/test_static.py::test_e2e_fallback_filename[/other-index.raise-None-None-True] tests/test_static.py::test_e2e_fallback_filename[/other-index.raise-None-None-False] tests/test_static.py::test_match[None-/static-False] tests/test_static.py::test_match[None-/static/-True] tests/test_static.py::test_match[None-/staticfoo-False] tests/test_static.py::test_match[None-/static/foo-True] tests/test_static.py::test_match[index2-/static-True] tests/test_static.py::test_match[index2-/static/-True] tests/test_static.py::test_match[index2-/staticfoo-False] tests/test_static.py::test_match[index2-/static/foo-True] tests/test_uri_converters.py::test_uuid_converter[aef90600-660f-41e2-b929-3bf0177b412c-expected0] tests/test_uri_converters.py::test_uuid_converter[aef90600660f-41e2-b929-3bf0177b412c-expected1] tests/test_uri_converters.py::test_uuid_converter[aef90600660f41e2b9293bf0177b412c-expected2] tests/test_uri_converters.py::test_uuid_converter[urn:uuid:aef90600-660f-41e2-b929-3bf0177b412c-expected3] tests/test_uri_converters.py::test_uuid_converter[urn:uuid:aef90600660f41e2b9293bf0177b412c-expected4] tests/test_uri_converters.py::test_uuid_converter[aef90600-660f-41e2-b929-3bf0177b412c tests/test_uri_converters.py::test_uuid_converter[aef90600-660f-41e2-b929-3bf0177b412-None] tests/test_uri_converters.py::test_uuid_converter[a-None] tests/test_uri_converters.py::test_uuid_converter[aef90600-660f-41e2-b929-3bf0177b412g-None] tests/test_uri_converters.py::test_uuid_converter[aef90600_660f_41e2_b929_3bf0177b412c-None] tests/test_uri_templates.py::test_uuid_converter[/widgets/{widget_id:uuid}-/widgets/54ecb214-db2b-41c1-9ac4-2926ca435ad3-expected0] tests/test_uri_templates.py::test_uuid_converter[/widgets/{widget_id:uuid}/orders-/widgets/54ecb214db2b41c19ac42926ca435ad3/orders-expected1] tests/test_uri_templates.py::test_uuid_converter[/versions/diff/{left:uuid()}...{right:uuid()}-/versions/diff/54ecb214-db2b-41c1-9ac4-2926ca435ad3...bdf6817f-2e1f-48a6-b68a-75852b23332c-expected2] tests/test_uri_templates.py::test_uuid_converter[/versions/diff/{left:uuid}...{right:uuid()}-/versions/diff/54ecb214-db2b-41c1-9ac4-2926ca435ad3...bdf6817f-2e1f-48a6-b68a-75852b23332c-expected3] tests/test_uri_templates.py::test_uuid_converter[/versions/diff/{left:uuid()}...{right:uuid}-/versions/diff/54ecb214-db2b-41c1-9ac4-2926ca435ad3...bdf6817f-2e1f-48a6-b68a-75852b23332c-expected4] tests/test_uri_templates.py::test_uuid_converter[/widgets/{widget_id:uuid}/orders-/widgets/54ecb214db2b41c19ac42926ca435ad/orders-None]
tests/test_httperror.py::TestHTTPError::test_custom_old_error_serializer tests/test_httperror.py::TestHTTPError::test_custom_new_error_serializer tests/test_request_media.py::test_msgpack[application/msgpack] tests/test_request_media.py::test_msgpack[application/msgpack; tests/test_request_media.py::test_msgpack[application/x-msgpack] tests/test_request_media.py::test_invalid_msgpack tests/test_response_media.py::test_msgpack[application/msgpack] tests/test_response_media.py::test_msgpack[application/msgpack; tests/test_response_media.py::test_msgpack[application/x-msgpack]
tests/test_after_hooks.py::test_output_validator tests/test_after_hooks.py::test_serializer tests/test_after_hooks.py::test_hook_as_callable_class tests/test_after_hooks.py::test_resource_with_uri_fields[resource0] tests/test_after_hooks.py::test_resource_with_uri_fields[resource1] tests/test_after_hooks.py::test_wrapped_resource[resource0] tests/test_after_hooks.py::test_wrapped_resource[resource1] tests/test_after_hooks.py::test_wrapped_resource_with_hooks_aware_of_resource tests/test_before_hooks.py::test_multiple_resource_hooks[resource0] tests/test_before_hooks.py::test_multiple_resource_hooks[resource1] tests/test_before_hooks.py::test_input_validator tests/test_before_hooks.py::test_input_validator_inherited tests/test_before_hooks.py::test_param_validator tests/test_before_hooks.py::test_field_validator[resource0] tests/test_before_hooks.py::test_field_validator[resource1] tests/test_before_hooks.py::test_field_validator[resource2] tests/test_before_hooks.py::test_parser tests/test_before_hooks.py::test_wrapped_resource tests/test_before_hooks.py::test_wrapped_resource_with_hooks_aware_of_resource tests/test_boundedstream.py::test_not_writeable tests/test_cmd_print_api.py::test_traverse_with_verbose tests/test_cmd_print_api.py::test_traverse tests/test_cookies.py::test_response_base_case tests/test_cookies.py::test_response_disable_secure_globally tests/test_cookies.py::test_response_complex_case tests/test_cookies.py::test_cookie_expires_naive tests/test_cookies.py::test_cookie_expires_aware tests/test_cookies.py::test_cookies_setable tests/test_cookies.py::test_cookie_max_age_float_and_string[foofloat] tests/test_cookies.py::test_cookie_max_age_float_and_string[foostring] tests/test_cookies.py::test_response_unset_cookie tests/test_cookies.py::test_cookie_timezone tests/test_cookies.py::test_request_cookie_parsing tests/test_cookies.py::test_invalid_cookies_are_ignored tests/test_cookies.py::test_cookie_header_is_missing tests/test_cookies.py::test_unicode_inside_ascii_range tests/test_cookies.py::test_non_ascii_name[Unicode_\xc3\xa6\xc3\xb8] tests/test_cookies.py::test_non_ascii_name[Unicode_\xc3\x83\xc2\xa6\xc3\x83\xc2\xb8] tests/test_cookies.py::test_non_ascii_name[42] tests/test_cookies.py::test_non_ascii_value[Unicode_\xc3\xa6\xc3\xb8] tests/test_cookies.py::test_non_ascii_value[Unicode_\xc3\x83\xc2\xa6\xc3\x83\xc2\xb8] tests/test_cookies.py::test_non_ascii_value[42] tests/test_custom_router.py::test_custom_router_add_route_should_be_used tests/test_custom_router.py::test_custom_router_find_should_be_used tests/test_custom_router.py::test_can_pass_additional_params_to_add_route tests/test_custom_router.py::test_custom_router_takes_req_positional_argument tests/test_custom_router.py::test_custom_router_takes_req_keyword_argument tests/test_default_router.py::test_user_regression_versioned_url tests/test_default_router.py::test_user_regression_recipes tests/test_default_router.py::test_user_regression_special_chars[/serviceRoot/People|{field}-/serviceRoot/People|susie-expected_params0] tests/test_default_router.py::test_user_regression_special_chars[/serviceRoot/People[{field}]-/serviceRoot/People['calvin']-expected_params1] tests/test_default_router.py::test_user_regression_special_chars[/serviceRoot/People({field})-/serviceRoot/People('hobbes')-expected_params2] tests/test_default_router.py::test_user_regression_special_chars[/serviceRoot/People({field})-/serviceRoot/People('hob)bes')-expected_params3] tests/test_default_router.py::test_user_regression_special_chars[/serviceRoot/People({field})(z)-/serviceRoot/People(hobbes)(z)-expected_params4] tests/test_default_router.py::test_user_regression_special_chars[/serviceRoot/People('{field}')-/serviceRoot/People('rosalyn')-expected_params5] tests/test_default_router.py::test_user_regression_special_chars[/^{field}-/^42-expected_params6] tests/test_default_router.py::test_user_regression_special_chars[/+{field}-/+42-expected_params7] tests/test_default_router.py::test_user_regression_special_chars[/foo/{first}_{second}/bar-/foo/abc_def_ghijk/bar-expected_params8] tests/test_default_router.py::test_user_regression_special_chars[/items/{x}?{y}-/items/1080?768-expected_params9] tests/test_default_router.py::test_user_regression_special_chars[/items/{x}|{y}-/items/1080|768-expected_params10] tests/test_default_router.py::test_user_regression_special_chars[/items/{x},{y}-/items/1080,768-expected_params11] tests/test_default_router.py::test_user_regression_special_chars[/items/{x}^^{y}-/items/1080^^768-expected_params12] tests/test_default_router.py::test_user_regression_special_chars[/items/{x}*{y}*-/items/1080*768*-expected_params13] tests/test_default_router.py::test_user_regression_special_chars[/thing-2/something+{field}+-/thing-2/something+42+-expected_params14] tests/test_default_router.py::test_user_regression_special_chars[/thing-2/something*{field}/notes-/thing-2/something*42/notes-expected_params15] tests/test_default_router.py::test_user_regression_special_chars[/thing-2/something+{field}|{q}/notes-/thing-2/something+else|z/notes-expected_params16] tests/test_default_router.py::test_user_regression_special_chars[serviceRoot/$metadata#Airports('{field}')/Name-serviceRoot/$metadata#Airports('KSFO')/Name-expected_params17] tests/test_default_router.py::test_not_str[uri_template0] tests/test_default_router.py::test_not_str[uri_template1] tests/test_default_router.py::test_not_str[uri_template2] tests/test_default_router.py::test_root_path tests/test_default_router.py::test_duplicate_field_names[/{field}{field}] tests/test_default_router.py::test_duplicate_field_names[/{field}...{field}] tests/test_default_router.py::test_duplicate_field_names[/{field}/{another}/{field}] tests/test_default_router.py::test_duplicate_field_names[/{field}/something/something/{field}/something] tests/test_default_router.py::test_match_entire_path[/items/thing-/items/t] tests/test_default_router.py::test_match_entire_path[/items/{x}|{y}|-/items/1080|768] tests/test_default_router.py::test_match_entire_path[/items/{x}*{y}foo-/items/1080*768foobar] tests/test_default_router.py::test_match_entire_path[/items/{x}*768*-/items/1080*768***] tests/test_default_router.py::test_conflict[/teams/{conflict}] tests/test_default_router.py::test_conflict[/emojis/signs/{id_too}] tests/test_default_router.py::test_conflict[/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}:{conflict}] tests/test_default_router.py::test_conflict[/teams/{id:int}/settings] tests/test_default_router.py::test_non_conflict[/repos/{org}/{repo}/compare/{simple_vs_complex}] tests/test_default_router.py::test_non_conflict[/repos/{complex}.{vs}.{simple}] tests/test_default_router.py::test_non_conflict[/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}/full] tests/test_default_router.py::test_invalid_field_name[/{}] tests/test_default_router.py::test_invalid_field_name[/repos/{org}/{repo}/compare/{}] tests/test_default_router.py::test_invalid_field_name[/repos/{complex}.{}.{thing}] tests/test_default_router.py::test_invalid_field_name[/{9v}] tests/test_default_router.py::test_invalid_field_name[/{524hello}/world] tests/test_default_router.py::test_invalid_field_name[/hello/{1world}] tests/test_default_router.py::test_invalid_field_name[/repos/{complex}.{9v}.{thing}/etc] tests/test_default_router.py::test_invalid_field_name[/{*kgriffs}] tests/test_default_router.py::test_invalid_field_name[/{@kgriffs}] tests/test_default_router.py::test_invalid_field_name[/repos/{complex}.{v}.{@thing}/etc] tests/test_default_router.py::test_invalid_field_name[/{-kgriffs}] tests/test_default_router.py::test_invalid_field_name[/repos/{complex}.{-v}.{thing}/etc] tests/test_default_router.py::test_invalid_field_name[/repos/{simple-thing}/etc] tests/test_default_router.py::test_invalid_field_name[/this tests/test_default_router.py::test_invalid_field_name[/this\tand\tthat/this\nand\nthat/{thing tests/test_default_router.py::test_invalid_field_name[/{thing\t}/world] tests/test_default_router.py::test_invalid_field_name[/{\nthing}/world] tests/test_default_router.py::test_invalid_field_name[/{th\x0bing}/world] tests/test_default_router.py::test_invalid_field_name[/{ tests/test_default_router.py::test_invalid_field_name[/{thing}/wo tests/test_default_router.py::test_invalid_field_name[/{thing} tests/test_default_router.py::test_invalid_field_name[/repos/{or tests/test_default_router.py::test_invalid_field_name[/repos/{org}/{repo}/compare/{th\ting}] tests/test_default_router.py::test_print_src tests/test_default_router.py::test_override tests/test_default_router.py::test_literal_segment tests/test_default_router.py::test_dead_segment[/teams] tests/test_default_router.py::test_dead_segment[/emojis/signs] tests/test_default_router.py::test_dead_segment[/gists] tests/test_default_router.py::test_dead_segment[/gists/42] tests/test_default_router.py::test_malformed_pattern[/repos/racker/falcon/compare/foo] tests/test_default_router.py::test_malformed_pattern[/repos/racker/falcon/compare/foo/full] tests/test_default_router.py::test_literal tests/test_default_router.py::test_converters[/cvt/teams/007-expected_params0] tests/test_default_router.py::test_converters[/cvt/teams/1234/members-expected_params1] tests/test_default_router.py::test_converters[/cvt/teams/default/members/700-5-expected_params2] tests/test_default_router.py::test_converters[/cvt/repos/org/repo/compare/xkcd:353-expected_params3] tests/test_default_router.py::test_converters[/cvt/repos/org/repo/compare/gunmachan:1234...kumamon:5678/part-expected_params4] tests/test_default_router.py::test_converters[/cvt/repos/xkcd/353/compare/susan:0001/full-expected_params5] tests/test_default_router.py::test_converters_with_invalid_options[/foo/{bar:int(0)}] tests/test_default_router.py::test_converters_with_invalid_options[/foo/{bar:int(num_digits=0)}] tests/test_default_router.py::test_converters_with_invalid_options[/foo/{bar:int(-1)}/baz] tests/test_default_router.py::test_converters_with_invalid_options[/foo/{bar:int(num_digits=-1)}/baz] tests/test_default_router.py::test_converters_malformed_specification[/foo/{bar:}] tests/test_default_router.py::test_converters_malformed_specification[/foo/{bar:unknown}/baz] tests/test_default_router.py::test_variable tests/test_default_router.py::test_single_character_field_name tests/test_default_router.py::test_literal_vs_variable[/teams/default-19] tests/test_default_router.py::test_literal_vs_variable[/teams/default/members-7] tests/test_default_router.py::test_literal_vs_variable[/cvt/teams/default-31] tests/test_default_router.py::test_literal_vs_variable[/cvt/teams/default/members/1234-10-32] tests/test_default_router.py::test_literal_vs_variable[/teams/1234-6] tests/test_default_router.py::test_literal_vs_variable[/teams/1234/members-7] tests/test_default_router.py::test_literal_vs_variable[/gists/first-20] tests/test_default_router.py::test_literal_vs_variable[/gists/first/raw-18] tests/test_default_router.py::test_literal_vs_variable[/gists/first/pdf-21] tests/test_default_router.py::test_literal_vs_variable[/gists/1776/pdf-21] tests/test_default_router.py::test_literal_vs_variable[/emojis/signs/78-13] tests/test_default_router.py::test_literal_vs_variable[/emojis/signs/78/small.png-24] tests/test_default_router.py::test_literal_vs_variable[/emojis/signs/78/small(png)-25] tests/test_default_router.py::test_literal_vs_variable[/emojis/signs/78/small_png-26] tests/test_default_router.py::test_not_found[/this/does/not/exist] tests/test_default_router.py::test_not_found[/user/bogus] tests/test_default_router.py::test_not_found[/repos/racker/falcon/compare/johndoe:master...janedoe:dev/bogus] tests/test_default_router.py::test_not_found[/teams] tests/test_default_router.py::test_not_found[/teams/42/members/undefined] tests/test_default_router.py::test_not_found[/teams/42/undefined] tests/test_default_router.py::test_not_found[/teams/42/undefined/segments] tests/test_default_router.py::test_not_found[/teams/default/members/undefined] tests/test_default_router.py::test_not_found[/teams/default/members/thing/undefined] tests/test_default_router.py::test_not_found[/teams/default/members/thing/undefined/segments] tests/test_default_router.py::test_not_found[/teams/default/undefined] tests/test_default_router.py::test_not_found[/teams/default/undefined/segments] tests/test_default_router.py::test_not_found[/cvt/teams/default/members] tests/test_default_router.py::test_not_found[/cvt/teams/NaN] tests/test_default_router.py::test_not_found[/cvt/teams/default/members/NaN] tests/test_default_router.py::test_not_found[/emojis/signs] tests/test_default_router.py::test_not_found[/emojis/signs/0/small] tests/test_default_router.py::test_not_found[/emojis/signs/0/undefined] tests/test_default_router.py::test_not_found[/emojis/signs/0/undefined/segments] tests/test_default_router.py::test_not_found[/emojis/signs/20/small] tests/test_default_router.py::test_not_found[/emojis/signs/20/undefined] tests/test_default_router.py::test_not_found[/emojis/signs/42/undefined] tests/test_default_router.py::test_not_found[/emojis/signs/78/undefined] tests/test_default_router.py::test_subsegment_not_found tests/test_default_router.py::test_multivar tests/test_default_router.py::test_complex[-5] tests/test_default_router.py::test_complex[/full-10] tests/test_default_router.py::test_complex[/part-15] tests/test_default_router.py::test_complex_alt[-16-/repos/{org}/{repo}/compare/{usr0}:{branch0}] tests/test_default_router.py::test_complex_alt[/full-17-/repos/{org}/{repo}/compare/{usr0}:{branch0}/full] tests/test_default_router.py::test_options_converters_set tests/test_default_router.py::test_options_converters_update[spam] tests/test_default_router.py::test_options_converters_update[spam_2] tests/test_default_router.py::test_options_converters_invalid_name[has tests/test_default_router.py::test_options_converters_invalid_name[whitespace tests/test_default_router.py::test_options_converters_invalid_name[ tests/test_default_router.py::test_options_converters_invalid_name[funky$character] tests/test_default_router.py::test_options_converters_invalid_name[42istheanswer] tests/test_default_router.py::test_options_converters_invalid_name[with-hyphen] tests/test_default_router.py::test_options_converters_invalid_name_on_update tests/test_deps.py::test_deps_mimeparse_correct_package tests/test_error.py::test_with_default_title_and_desc[HTTPBadRequest-400 tests/test_error.py::test_with_default_title_and_desc[HTTPForbidden-403 tests/test_error.py::test_with_default_title_and_desc[HTTPConflict-409 tests/test_error.py::test_with_default_title_and_desc[HTTPLengthRequired-411 tests/test_error.py::test_with_default_title_and_desc[HTTPPreconditionFailed-412 tests/test_error.py::test_with_default_title_and_desc[HTTPRequestEntityTooLarge-413 tests/test_error.py::test_with_default_title_and_desc[HTTPUriTooLong-414 tests/test_error.py::test_with_default_title_and_desc[HTTPUnprocessableEntity-422 tests/test_error.py::test_with_default_title_and_desc[HTTPLocked-423 tests/test_error.py::test_with_default_title_and_desc[HTTPFailedDependency-424 tests/test_error.py::test_with_default_title_and_desc[HTTPPreconditionRequired-428 tests/test_error.py::test_with_default_title_and_desc[HTTPTooManyRequests-429 tests/test_error.py::test_with_default_title_and_desc[HTTPRequestHeaderFieldsTooLarge-431 tests/test_error.py::test_with_default_title_and_desc[HTTPUnavailableForLegalReasons-451 tests/test_error.py::test_with_default_title_and_desc[HTTPInternalServerError-500 tests/test_error.py::test_with_default_title_and_desc[HTTPNotImplemented-501 tests/test_error.py::test_with_default_title_and_desc[HTTPBadGateway-502 tests/test_error.py::test_with_default_title_and_desc[HTTPServiceUnavailable-503 tests/test_error.py::test_with_default_title_and_desc[HTTPGatewayTimeout-504 tests/test_error.py::test_with_default_title_and_desc[HTTPVersionNotSupported-505 tests/test_error.py::test_with_default_title_and_desc[HTTPInsufficientStorage-507 tests/test_error.py::test_with_default_title_and_desc[HTTPLoopDetected-508 tests/test_error.py::test_with_default_title_and_desc[HTTPNetworkAuthenticationRequired-511 tests/test_error.py::test_with_title_and_desc[HTTPBadRequest] tests/test_error.py::test_with_title_and_desc[HTTPForbidden] tests/test_error.py::test_with_title_and_desc[HTTPConflict] tests/test_error.py::test_with_title_and_desc[HTTPLengthRequired] tests/test_error.py::test_with_title_and_desc[HTTPPreconditionFailed] tests/test_error.py::test_with_title_and_desc[HTTPPreconditionRequired] tests/test_error.py::test_with_title_and_desc[HTTPUriTooLong] tests/test_error.py::test_with_title_and_desc[HTTPUnprocessableEntity] tests/test_error.py::test_with_title_and_desc[HTTPLocked] tests/test_error.py::test_with_title_and_desc[HTTPFailedDependency] tests/test_error.py::test_with_title_and_desc[HTTPRequestHeaderFieldsTooLarge] tests/test_error.py::test_with_title_and_desc[HTTPUnavailableForLegalReasons] tests/test_error.py::test_with_title_and_desc[HTTPInternalServerError] tests/test_error.py::test_with_title_and_desc[HTTPNotImplemented] tests/test_error.py::test_with_title_and_desc[HTTPBadGateway] tests/test_error.py::test_with_title_and_desc[HTTPServiceUnavailable] tests/test_error.py::test_with_title_and_desc[HTTPGatewayTimeout] tests/test_error.py::test_with_title_and_desc[HTTPVersionNotSupported] tests/test_error.py::test_with_title_and_desc[HTTPInsufficientStorage] tests/test_error.py::test_with_title_and_desc[HTTPLoopDetected] tests/test_error.py::test_with_title_and_desc[HTTPNetworkAuthenticationRequired] tests/test_error.py::test_with_retry_after[HTTPServiceUnavailable] tests/test_error.py::test_with_retry_after[HTTPTooManyRequests] tests/test_error.py::test_with_retry_after[HTTPRequestEntityTooLarge] tests/test_error.py::test_http_unauthorized_no_title_and_desc_and_challenges tests/test_error.py::test_http_unauthorized_with_title_and_desc_and_challenges tests/test_error.py::test_http_not_acceptable_no_title_and_desc_and_challenges tests/test_error.py::test_http_not_acceptable_with_title_and_desc_and_challenges tests/test_error.py::test_http_unsupported_media_type_no_title_and_desc_and_challenges tests/test_error.py::test_http_unsupported_media_type_with_title_and_desc_and_challenges tests/test_error.py::test_http_error_repr tests/test_error_handlers.py::TestErrorHandler::test_caught_error tests/test_error_handlers.py::TestErrorHandler::test_uncaught_error tests/test_error_handlers.py::TestErrorHandler::test_uncaught_error_else tests/test_error_handlers.py::TestErrorHandler::test_converted_error tests/test_error_handlers.py::TestErrorHandler::test_handle_not_defined tests/test_error_handlers.py::TestErrorHandler::test_subclass_error tests/test_error_handlers.py::TestErrorHandler::test_error_order_duplicate tests/test_error_handlers.py::TestErrorHandler::test_error_order_subclass tests/test_error_handlers.py::TestErrorHandler::test_error_order_subclass_masked tests/test_headers.py::TestHeaders::test_content_length tests/test_headers.py::TestHeaders::test_default_value tests/test_headers.py::TestHeaders::test_unset_header tests/test_headers.py::TestHeaders::test_required_header tests/test_headers.py::TestHeaders::test_no_content_length[204 tests/test_headers.py::TestHeaders::test_no_content_length[304 tests/test_headers.py::TestHeaders::test_content_header_missing tests/test_headers.py::TestHeaders::test_passthrough_request_headers tests/test_headers.py::TestHeaders::test_headers_as_list tests/test_headers.py::TestHeaders::test_default_media_type tests/test_headers.py::TestHeaders::test_override_default_media_type[text/plain; tests/test_headers.py::TestHeaders::test_override_default_media_type[text/plain-Hello tests/test_headers.py::TestHeaders::test_override_default_media_type_missing_encoding tests/test_headers.py::TestHeaders::test_response_header_helpers_on_get tests/test_headers.py::TestHeaders::test_unicode_location_headers tests/test_headers.py::TestHeaders::test_unicode_headers_convertable tests/test_headers.py::TestHeaders::test_response_set_and_get_header tests/test_headers.py::TestHeaders::test_response_append_header tests/test_headers.py::TestHeaders::test_vary_star tests/test_headers.py::TestHeaders::test_vary_header[vary0-accept-encoding] tests/test_headers.py::TestHeaders::test_vary_header[vary1-accept-encoding, tests/test_headers.py::TestHeaders::test_vary_header[vary2-accept-encoding, tests/test_headers.py::TestHeaders::test_content_type_no_body tests/test_headers.py::TestHeaders::test_no_content_type[204 tests/test_headers.py::TestHeaders::test_no_content_type[304 tests/test_headers.py::TestHeaders::test_custom_content_type tests/test_headers.py::TestHeaders::test_add_link_single tests/test_headers.py::TestHeaders::test_add_link_multiple tests/test_headers.py::TestHeaders::test_add_link_with_title tests/test_headers.py::TestHeaders::test_add_link_with_title_star tests/test_headers.py::TestHeaders::test_add_link_with_anchor tests/test_headers.py::TestHeaders::test_add_link_with_hreflang tests/test_headers.py::TestHeaders::test_add_link_with_hreflang_multi tests/test_headers.py::TestHeaders::test_add_link_with_type_hint tests/test_headers.py::TestHeaders::test_add_link_complex tests/test_headers.py::TestHeaders::test_content_length_options tests/test_hello.py::TestHelloWorld::test_env_headers_list_of_tuples tests/test_hello.py::TestHelloWorld::test_root_route tests/test_hello.py::TestHelloWorld::test_no_route tests/test_hello.py::TestHelloWorld::test_body[/body-resource0-<lambda>] tests/test_hello.py::TestHelloWorld::test_body[/bytes-resource1-<lambda>] tests/test_hello.py::TestHelloWorld::test_body[/data-resource2-<lambda>] tests/test_hello.py::TestHelloWorld::test_no_body_on_head tests/test_hello.py::TestHelloWorld::test_stream_chunked tests/test_hello.py::TestHelloWorld::test_stream_known_len tests/test_hello.py::TestHelloWorld::test_filelike tests/test_hello.py::TestHelloWorld::test_filelike_closing[ClosingBytesIO-True] tests/test_hello.py::TestHelloWorld::test_filelike_closing[NonClosingBytesIO-False] tests/test_hello.py::TestHelloWorld::test_filelike_using_helper tests/test_hello.py::TestHelloWorld::test_status_not_set tests/test_http_method_routing.py::TestHttpMethodRouting::test_get tests/test_http_method_routing.py::TestHttpMethodRouting::test_put tests/test_http_method_routing.py::TestHttpMethodRouting::test_post_not_allowed tests/test_http_method_routing.py::TestHttpMethodRouting::test_report tests/test_http_method_routing.py::TestHttpMethodRouting::test_misc tests/test_http_method_routing.py::TestHttpMethodRouting::test_methods_not_allowed_simple tests/test_http_method_routing.py::TestHttpMethodRouting::test_methods_not_allowed_complex tests/test_http_method_routing.py::TestHttpMethodRouting::test_method_not_allowed_with_param tests/test_http_method_routing.py::TestHttpMethodRouting::test_default_on_options tests/test_http_method_routing.py::TestHttpMethodRouting::test_on_options tests/test_http_method_routing.py::TestHttpMethodRouting::test_bogus_method tests/test_httperror.py::TestHTTPError::test_base_class tests/test_httperror.py::TestHTTPError::test_no_description_json tests/test_httperror.py::TestHTTPError::test_no_description_xml tests/test_httperror.py::TestHTTPError::test_client_does_not_accept_json_or_xml tests/test_httperror.py::TestHTTPError::test_custom_old_error_serializer_no_body tests/test_httperror.py::TestHTTPError::test_client_does_not_accept_anything tests/test_httperror.py::TestHTTPError::test_forbidden[application/json] tests/test_httperror.py::TestHTTPError::test_forbidden[application/vnd.company.system.project.resource+json;v=1.1] tests/test_httperror.py::TestHTTPError::test_forbidden[application/json-patch+json] tests/test_httperror.py::TestHTTPError::test_epic_fail_json tests/test_httperror.py::TestHTTPError::test_epic_fail_xml[text/xml] tests/test_httperror.py::TestHTTPError::test_epic_fail_xml[application/xml] tests/test_httperror.py::TestHTTPError::test_epic_fail_xml[application/vnd.company.system.project.resource+xml;v=1.1] tests/test_httperror.py::TestHTTPError::test_epic_fail_xml[application/atom+xml] tests/test_httperror.py::TestHTTPError::test_unicode_json tests/test_httperror.py::TestHTTPError::test_unicode_xml tests/test_httperror.py::TestHTTPError::test_401 tests/test_httperror.py::TestHTTPError::test_404_without_body tests/test_httperror.py::TestHTTPError::test_404_with_body tests/test_httperror.py::TestHTTPError::test_405_without_body tests/test_httperror.py::TestHTTPError::test_405_without_body_with_extra_headers tests/test_httperror.py::TestHTTPError::test_405_without_body_with_extra_headers_double_check tests/test_httperror.py::TestHTTPError::test_405_with_body tests/test_httperror.py::TestHTTPError::test_410_without_body tests/test_httperror.py::TestHTTPError::test_410_with_body tests/test_httperror.py::TestHTTPError::test_411 tests/test_httperror.py::TestHTTPError::test_413 tests/test_httperror.py::TestHTTPError::test_temporary_413_integer_retry_after tests/test_httperror.py::TestHTTPError::test_temporary_413_datetime_retry_after tests/test_httperror.py::TestHTTPError::test_414 tests/test_httperror.py::TestHTTPError::test_414_with_title tests/test_httperror.py::TestHTTPError::test_414_with_description tests/test_httperror.py::TestHTTPError::test_414_with_custom_kwargs tests/test_httperror.py::TestHTTPError::test_416 tests/test_httperror.py::TestHTTPError::test_429_no_retry_after tests/test_httperror.py::TestHTTPError::test_429 tests/test_httperror.py::TestHTTPError::test_429_datetime tests/test_httperror.py::TestHTTPError::test_503_integer_retry_after tests/test_httperror.py::TestHTTPError::test_503_datetime_retry_after tests/test_httperror.py::TestHTTPError::test_invalid_header tests/test_httperror.py::TestHTTPError::test_missing_header tests/test_httperror.py::TestHTTPError::test_invalid_param tests/test_httperror.py::TestHTTPError::test_missing_param tests/test_httperror.py::TestHTTPError::test_misc tests/test_httperror.py::TestHTTPError::test_title_default_message_if_none tests/test_httpstatus.py::TestHTTPStatus::test_raise_status_in_before_hook tests/test_httpstatus.py::TestHTTPStatus::test_raise_status_in_responder tests/test_httpstatus.py::TestHTTPStatus::test_raise_status_runs_after_hooks tests/test_httpstatus.py::TestHTTPStatus::test_raise_status_survives_after_hooks tests/test_httpstatus.py::TestHTTPStatus::test_raise_status_empty_body tests/test_httpstatus.py::TestHTTPStatusWithMiddleware::test_raise_status_in_process_request tests/test_httpstatus.py::TestHTTPStatusWithMiddleware::test_raise_status_in_process_resource tests/test_httpstatus.py::TestHTTPStatusWithMiddleware::test_raise_status_runs_process_response tests/test_media_handlers.py::test_base_handler_contract tests/test_middleware.py::TestRequestTimeMiddleware::test_skip_process_resource tests/test_middleware.py::TestRequestTimeMiddleware::test_add_invalid_middleware tests/test_middleware.py::TestRequestTimeMiddleware::test_response_middleware_raises_exception tests/test_middleware.py::TestRequestTimeMiddleware::test_log_get_request tests/test_middleware.py::TestTransactionIdMiddleware::test_generate_trans_id_with_request tests/test_middleware.py::TestSeveralMiddlewares::test_generate_trans_id_and_time_with_request tests/test_middleware.py::TestSeveralMiddlewares::test_legacy_middleware_called_with_correct_args tests/test_middleware.py::TestSeveralMiddlewares::test_middleware_execution_order tests/test_middleware.py::TestSeveralMiddlewares::test_independent_middleware_execution_order tests/test_middleware.py::TestSeveralMiddlewares::test_multiple_reponse_mw_throw_exception tests/test_middleware.py::TestSeveralMiddlewares::test_inner_mw_throw_exception tests/test_middleware.py::TestSeveralMiddlewares::test_inner_mw_with_ex_handler_throw_exception tests/test_middleware.py::TestSeveralMiddlewares::test_outer_mw_with_ex_handler_throw_exception tests/test_middleware.py::TestSeveralMiddlewares::test_order_mw_executed_when_exception_in_resp tests/test_middleware.py::TestSeveralMiddlewares::test_order_independent_mw_executed_when_exception_in_resp tests/test_middleware.py::TestSeveralMiddlewares::test_order_mw_executed_when_exception_in_req tests/test_middleware.py::TestSeveralMiddlewares::test_order_independent_mw_executed_when_exception_in_req tests/test_middleware.py::TestSeveralMiddlewares::test_order_mw_executed_when_exception_in_rsrc tests/test_middleware.py::TestSeveralMiddlewares::test_order_independent_mw_executed_when_exception_in_rsrc tests/test_middleware.py::TestRemoveBasePathMiddleware::test_base_path_is_removed_before_routing tests/test_middleware.py::TestResourceMiddleware::test_can_access_resource_params tests/test_middleware.py::TestErrorHandling::test_error_composed_before_resp_middleware_called tests/test_middleware.py::TestErrorHandling::test_http_status_raised_from_error_handler tests/test_options.py::TestRequestOptions::test_option_defaults tests/test_options.py::TestRequestOptions::test_options_toggle[keep_blank_qs_values] tests/test_options.py::TestRequestOptions::test_options_toggle[auto_parse_form_urlencoded] tests/test_options.py::TestRequestOptions::test_options_toggle[auto_parse_qs_csv] tests/test_options.py::TestRequestOptions::test_options_toggle[strip_url_path_trailing_slash] tests/test_options.py::TestRequestOptions::test_incorrect_options tests/test_query_params.py::TestQueryParams::test_none[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_none[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_blank[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_blank[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_simple[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_simple[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_percent_encoded[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_percent_encoded[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_option_auto_parse_qs_csv_simple_false[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_option_auto_parse_qs_csv_simple_false[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_option_auto_parse_qs_csv_simple_true[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_option_auto_parse_qs_csv_simple_true[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_option_auto_parse_qs_csv_complex_false[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_option_auto_parse_qs_csv_complex_false[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_bad_percentage[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_bad_percentage[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_allowed_names[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_allowed_names[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param-simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param-simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param_as_int-simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param_as_int-simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param_as_uuid-simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param_as_uuid-simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param_as_bool-simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param_as_bool-simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param_as_list-simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_required[get_param_as_list-simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_int[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_int[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_int_neg[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_int_neg[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_uuid[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_uuid[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_boolean[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_boolean[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_boolean_blank[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_boolean_blank[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_list_type[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_list_type[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_list_type_blank[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_list_type_blank[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_list_transformer[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_list_transformer[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_param_property[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_param_property[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_multiple_form_keys[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_multiple_form_keys[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_multiple_keys_as_bool[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_multiple_keys_as_bool[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_multiple_keys_as_int[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_multiple_keys_as_int[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_multiple_form_keys_as_list[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_multiple_form_keys_as_list[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_valid[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_valid[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_missing_param[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_missing_param[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_valid_with_format[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_valid_with_format[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_store[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_store[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_invalid[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_date_invalid[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_valid[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_valid[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_missing_param[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_missing_param[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_valid_with_format[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_valid_with_format[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_store[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_store[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_invalid[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_datetime_invalid[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_dict_valid[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_dict_valid[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_dict_missing_param[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_dict_missing_param[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_dict_store[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_dict_store[simulate_request_post_query_params] tests/test_query_params.py::TestQueryParams::test_get_dict_invalid[simulate_request_get_query_params] tests/test_query_params.py::TestQueryParams::test_get_dict_invalid[simulate_request_post_query_params] tests/test_query_params.py::TestPostQueryParams::test_http_methods_body_expected[POST] tests/test_query_params.py::TestPostQueryParams::test_http_methods_body_expected[PUT] tests/test_query_params.py::TestPostQueryParams::test_http_methods_body_expected[PATCH] tests/test_query_params.py::TestPostQueryParams::test_http_methods_body_expected[DELETE] tests/test_query_params.py::TestPostQueryParams::test_http_methods_body_expected[OPTIONS] tests/test_query_params.py::TestPostQueryParams::test_http_methods_body_not_expected[GET] tests/test_query_params.py::TestPostQueryParams::test_http_methods_body_not_expected[HEAD] tests/test_query_params.py::TestPostQueryParams::test_non_ascii tests/test_query_params.py::TestPostQueryParams::test_empty_body tests/test_query_params.py::TestPostQueryParams::test_empty_body_no_content_length tests/test_query_params.py::TestPostQueryParams::test_explicitly_disable_auto_parse tests/test_query_params.py::TestPostQueryParamsDefaultBehavior::test_dont_auto_parse_by_default tests/test_redirects.py::TestRedirects::test_redirect[GET-301 tests/test_redirects.py::TestRedirects::test_redirect[POST-302 tests/test_redirects.py::TestRedirects::test_redirect[PUT-303 tests/test_redirects.py::TestRedirects::test_redirect[DELETE-307 tests/test_redirects.py::TestRedirects::test_redirect[HEAD-308 tests/test_request_access_route.py::test_remote_addr_only tests/test_request_access_route.py::test_rfc_forwarded tests/test_request_access_route.py::test_malformed_rfc_forwarded tests/test_request_access_route.py::test_x_forwarded_for tests/test_request_access_route.py::test_x_real_ip tests/test_request_access_route.py::test_remote_addr tests/test_request_access_route.py::test_remote_addr_missing tests/test_request_attrs.py::TestRequestAttributes::test_missing_qs tests/test_request_attrs.py::TestRequestAttributes::test_empty tests/test_request_attrs.py::TestRequestAttributes::test_host tests/test_request_attrs.py::TestRequestAttributes::test_subdomain tests/test_request_attrs.py::TestRequestAttributes::test_reconstruct_url tests/test_request_attrs.py::TestRequestAttributes::test_nonlatin_path[/hello_\u043f\u0440\u0438\u0432\u0435\u0442] tests/test_request_attrs.py::TestRequestAttributes::test_nonlatin_path[/test/%E5%BB%B6%E5%AE%89] tests/test_request_attrs.py::TestRequestAttributes::test_nonlatin_path[/test/%C3%A4%C3%B6%C3%BC%C3%9F%E2%82%AC] tests/test_request_attrs.py::TestRequestAttributes::test_uri tests/test_request_attrs.py::TestRequestAttributes::test_uri_https tests/test_request_attrs.py::TestRequestAttributes::test_uri_http_1_0 tests/test_request_attrs.py::TestRequestAttributes::test_relative_uri tests/test_request_attrs.py::TestRequestAttributes::test_client_accepts tests/test_request_attrs.py::TestRequestAttributes::test_client_accepts_bogus tests/test_request_attrs.py::TestRequestAttributes::test_client_accepts_props tests/test_request_attrs.py::TestRequestAttributes::test_client_prefers tests/test_request_attrs.py::TestRequestAttributes::test_range tests/test_request_attrs.py::TestRequestAttributes::test_range_unit tests/test_request_attrs.py::TestRequestAttributes::test_range_invalid tests/test_request_attrs.py::TestRequestAttributes::test_missing_attribute_header tests/test_request_attrs.py::TestRequestAttributes::test_content_length tests/test_request_attrs.py::TestRequestAttributes::test_bogus_content_length_nan tests/test_request_attrs.py::TestRequestAttributes::test_bogus_content_length_neg tests/test_request_attrs.py::TestRequestAttributes::test_date[Date-date] tests/test_request_attrs.py::TestRequestAttributes::test_date[If-Modified-Since-if_modified_since] tests/test_request_attrs.py::TestRequestAttributes::test_date[If-Unmodified-Since-if_unmodified_since] tests/test_request_attrs.py::TestRequestAttributes::test_date_invalid[Date-date] tests/test_request_attrs.py::TestRequestAttributes::test_date_invalid[If-Modified-Since-if_modified_since] tests/test_request_attrs.py::TestRequestAttributes::test_date_invalid[If-Unmodified-Since-if_unmodified_since] tests/test_request_attrs.py::TestRequestAttributes::test_date_missing[date] tests/test_request_attrs.py::TestRequestAttributes::test_date_missing[if_modified_since] tests/test_request_attrs.py::TestRequestAttributes::test_date_missing[if_unmodified_since] tests/test_request_attrs.py::TestRequestAttributes::test_attribute_headers tests/test_request_attrs.py::TestRequestAttributes::test_method tests/test_request_attrs.py::TestRequestAttributes::test_empty_path tests/test_request_attrs.py::TestRequestAttributes::test_content_type_method tests/test_request_attrs.py::TestRequestAttributes::test_content_length_method tests/test_request_attrs.py::TestRequestAttributes::test_port_explicit[HTTP/1.0] tests/test_request_attrs.py::TestRequestAttributes::test_port_explicit[HTTP/1.1] tests/test_request_attrs.py::TestRequestAttributes::test_scheme_https[HTTP/1.0] tests/test_request_attrs.py::TestRequestAttributes::test_scheme_https[HTTP/1.1] tests/test_request_attrs.py::TestRequestAttributes::test_scheme_http[HTTP/1.0-True] tests/test_request_attrs.py::TestRequestAttributes::test_scheme_http[HTTP/1.0-False] tests/test_request_attrs.py::TestRequestAttributes::test_scheme_http[HTTP/1.1-True] tests/test_request_attrs.py::TestRequestAttributes::test_scheme_http[HTTP/1.1-False] tests/test_request_attrs.py::TestRequestAttributes::test_netloc_default_port[HTTP/1.0] tests/test_request_attrs.py::TestRequestAttributes::test_netloc_default_port[HTTP/1.1] tests/test_request_attrs.py::TestRequestAttributes::test_netloc_nondefault_port[HTTP/1.0] tests/test_request_attrs.py::TestRequestAttributes::test_netloc_nondefault_port[HTTP/1.1] tests/test_request_attrs.py::TestRequestAttributes::test_netloc_from_env[HTTP/1.0] tests/test_request_attrs.py::TestRequestAttributes::test_netloc_from_env[HTTP/1.1] tests/test_request_attrs.py::TestRequestAttributes::test_app_present tests/test_request_attrs.py::TestRequestAttributes::test_app_blank tests/test_request_attrs.py::TestRequestAttributes::test_app_missing tests/test_request_body.py::TestRequestBody::test_empty_body tests/test_request_body.py::TestRequestBody::test_tiny_body tests/test_request_body.py::TestRequestBody::test_tiny_body_overflow tests/test_request_body.py::TestRequestBody::test_read_body tests/test_request_body.py::TestRequestBody::test_bounded_stream_property_empty_body tests/test_request_body.py::TestRequestBody::test_body_stream_wrapper tests/test_request_body.py::TestRequestBody::test_request_repr tests/test_request_context.py::TestRequestContext::test_default_request_context tests/test_request_context.py::TestRequestContext::test_custom_request_context tests/test_request_context.py::TestRequestContext::test_custom_request_context_failure tests/test_request_context.py::TestRequestContext::test_custom_request_context_request_access tests/test_request_forwarded.py::test_no_forwarded_headers tests/test_request_forwarded.py::test_x_forwarded_host tests/test_request_forwarded.py::test_x_forwarded_proto tests/test_request_forwarded.py::test_forwarded_host tests/test_request_forwarded.py::test_forwarded_multiple_params tests/test_request_forwarded.py::test_forwarded_missing_first_hop_host tests/test_request_forwarded.py::test_forwarded_quote_escaping tests/test_request_forwarded.py::test_escape_malformed_requests[for=1.2.3.4;by="-None] tests/test_request_forwarded.py::test_escape_malformed_requests[for=1.2.3.4;by=4\\.3.2.1thing=blah-4] tests/test_request_forwarded.py::test_escape_malformed_requests[for=1.2.3.4;by="\\4.3.2.1"thing=blah-4.3.2.1] tests/test_request_forwarded.py::test_escape_malformed_requests[for=1.2.3.4;by="4.3.2.\\1"thing="blah"-4.3.2.1] tests/test_request_forwarded.py::test_escape_malformed_requests[for=1.2.3.4;by="4.3.\\2\\.1" tests/test_request_media.py::test_json[None] tests/test_request_media.py::test_json[*/*] tests/test_request_media.py::test_json[application/json] tests/test_request_media.py::test_json[application/json; tests/test_request_media.py::test_unknown_media_type[nope/json] tests/test_request_media.py::test_invalid_json tests/test_request_media.py::test_invalid_stream_fails_gracefully tests/test_request_media.py::test_use_cached_media tests/test_response.py::test_response_set_content_type_set tests/test_response.py::test_response_set_content_type_not_set tests/test_response_body.py::TestResponseBody::test_append_body tests/test_response_body.py::TestResponseBody::test_response_repr tests/test_response_context.py::TestRequestContext::test_default_response_context tests/test_response_context.py::TestRequestContext::test_custom_response_context tests/test_response_context.py::TestRequestContext::test_custom_response_context_failure tests/test_response_context.py::TestRequestContext::test_custom_response_context_factory tests/test_response_media.py::test_json[*/*] tests/test_response_media.py::test_json[application/json; tests/test_response_media.py::test_non_ascii_json_serialization[] tests/test_response_media.py::test_non_ascii_json_serialization[I tests/test_response_media.py::test_non_ascii_json_serialization[document2] tests/test_response_media.py::test_non_ascii_json_serialization[document3] tests/test_response_media.py::test_non_ascii_json_serialization[document4] tests/test_response_media.py::test_unknown_media_type tests/test_response_media.py::test_use_cached_media tests/test_response_media.py::test_default_media_type tests/test_response_media.py::test_mimeparse_edgecases tests/test_sinks.py::TestDefaultRouting::test_single_default_pattern tests/test_sinks.py::TestDefaultRouting::test_single_simple_pattern tests/test_sinks.py::TestDefaultRouting::test_single_compiled_pattern tests/test_sinks.py::TestDefaultRouting::test_named_groups tests/test_sinks.py::TestDefaultRouting::test_multiple_patterns tests/test_sinks.py::TestDefaultRouting::test_with_route tests/test_sinks.py::TestDefaultRouting::test_route_precedence tests/test_sinks.py::TestDefaultRouting::test_route_precedence_with_id tests/test_sinks.py::TestDefaultRouting::test_route_precedence_with_both_id tests/test_slots.py::TestSlots::test_slots_request tests/test_slots.py::TestSlots::test_slots_response tests/test_static.py::test_bad_path[/static] tests/test_static.py::test_bad_path[/static/] tests/test_static.py::test_bad_path[/static/.] tests/test_static.py::test_bad_path[/static/..] tests/test_static.py::test_bad_path[/static/../.] tests/test_static.py::test_bad_path[/static/.././etc/passwd] tests/test_static.py::test_bad_path[/static/../etc/passwd] tests/test_static.py::test_bad_path[/static/css/../../secret] tests/test_static.py::test_bad_path[/static/css/../../etc/passwd] tests/test_static.py::test_bad_path[/static/./../etc/passwd] tests/test_static.py::test_bad_path[/static/css/../.\\056/etc/passwd] tests/test_static.py::test_bad_path[/static/./\\056./etc/passwd] tests/test_static.py::test_bad_path[/static/\\056\\056/etc/passwd] tests/test_static.py::test_bad_path[/static//test.css] tests/test_static.py::test_bad_path[/static//COM10] tests/test_static.py::test_bad_path[/static/path//test.css] tests/test_static.py::test_bad_path[/static/path///test.css] tests/test_static.py::test_bad_path[/static/path////test.css] tests/test_static.py::test_bad_path[/static/path/foo//test.css] tests/test_static.py::test_bad_path[/static/.\x00ssh/authorized_keys] tests/test_static.py::test_bad_path[/static/.\x1fssh/authorized_keys] tests/test_static.py::test_bad_path[/static/.\x80ssh/authorized_keys] tests/test_static.py::test_bad_path[/static/.\x9fssh/authorized_keys] tests/test_static.py::test_bad_path[/static/~/.ssh/authorized_keys] tests/test_static.py::test_bad_path[/static/.ssh/authorized_key?] tests/test_static.py::test_bad_path[/static/.ssh/authorized_key>foo] tests/test_static.py::test_bad_path[/static/.ssh/authorized_key|foo] tests/test_static.py::test_bad_path[/static/.ssh/authorized_key<foo] tests/test_static.py::test_bad_path[/static/something:something] tests/test_static.py::test_bad_path[/static/thing*.sql] tests/test_static.py::test_bad_path[/static/'thing'.sql] tests/test_static.py::test_bad_path[/static/"thing".sql] tests/test_static.py::test_bad_path[/static/something.] tests/test_static.py::test_bad_path[/static/something..] tests/test_static.py::test_bad_path[/static/something tests/test_static.py::test_bad_path[/static/ tests/test_static.py::test_bad_path[/static/something\t] tests/test_static.py::test_bad_path[/static/\tsomething] tests/test_static.py::test_bad_path[/static/ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttx] tests/test_static.py::test_invalid_args[static-/var/www/statics] tests/test_static.py::test_invalid_args[/static-./var/www/statics] tests/test_static.py::test_invalid_args[/static-statics] tests/test_static.py::test_invalid_args[/static-../statics] tests/test_static.py::test_good_path[/static/-/css/test.css-/css/test.css-text/css] tests/test_static.py::test_good_path[/static-/css/test.css-/css/test.css-text/css] tests/test_static.py::test_good_path[/static-/tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt-/tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt-application/octet-stream] tests/test_static.py::test_good_path[/static-/.test.css-/.test.css-text/css] tests/test_static.py::test_good_path[/some/download/-/report.pdf-/report.pdf-application/pdf] tests/test_static.py::test_good_path[/some/download/-/Fancy tests/test_static.py::test_good_path[/some/download-/report.zip-/report.zip-application/zip] tests/test_static.py::test_good_path[/some/download-/foo/../report.zip-/report.zip-application/zip] tests/test_static.py::test_good_path[/some/download-/foo/../bar/../report.zip-/report.zip-application/zip] tests/test_static.py::test_good_path[/some/download-/foo/bar/../../report.zip-/report.zip-application/zip] tests/test_static.py::test_lifo tests/test_static.py::test_lifo_negative tests/test_static.py::test_downloadable tests/test_static.py::test_downloadable_not_found tests/test_uri_converters.py::test_int_converter[123-None-None-None-123] tests/test_uri_converters.py::test_int_converter[01-None-None-None-1] tests/test_uri_converters.py::test_int_converter[001-None-None-None-1] tests/test_uri_converters.py::test_int_converter[0-None-None-None-0] tests/test_uri_converters.py::test_int_converter[00-None-None-None-0] tests/test_uri_converters.py::test_int_converter[1-1-None-None-1] tests/test_uri_converters.py::test_int_converter[12-1-None-None-None0] tests/test_uri_converters.py::test_int_converter[12-2-None-None-120] tests/test_uri_converters.py::test_int_converter[1-1-1-1-1] tests/test_uri_converters.py::test_int_converter[1-1-1-None-1] tests/test_uri_converters.py::test_int_converter[1-1-1-2-1] tests/test_uri_converters.py::test_int_converter[1-1-2-None-None] tests/test_uri_converters.py::test_int_converter[1-1-2-1-None] tests/test_uri_converters.py::test_int_converter[2-1-1-2-2] tests/test_uri_converters.py::test_int_converter[2-1-2-2-2] tests/test_uri_converters.py::test_int_converter[3-1-1-2-None] tests/test_uri_converters.py::test_int_converter[12-1-None-None-None1] tests/test_uri_converters.py::test_int_converter[12-1-1-12-None] tests/test_uri_converters.py::test_int_converter[12-2-None-None-121] tests/test_uri_converters.py::test_int_converter[12-2-1-12-12] tests/test_uri_converters.py::test_int_converter[12-2-12-12-12] tests/test_uri_converters.py::test_int_converter[12-2-13-12-None] tests/test_uri_converters.py::test_int_converter[12-2-13-13-None] tests/test_uri_converters.py::test_int_converter_malformed[0x0F] tests/test_uri_converters.py::test_int_converter_malformed[something] tests/test_uri_converters.py::test_int_converter_malformed[] tests/test_uri_converters.py::test_int_converter_malformed[ tests/test_uri_converters.py::test_int_converter_malformed[123 tests/test_uri_converters.py::test_int_converter_malformed[123\t] tests/test_uri_converters.py::test_int_converter_malformed[123\n] tests/test_uri_converters.py::test_int_converter_malformed[123\r] tests/test_uri_converters.py::test_int_converter_malformed[123\x0b] tests/test_uri_converters.py::test_int_converter_malformed[123\x0c] tests/test_uri_converters.py::test_int_converter_malformed[\t123] tests/test_uri_converters.py::test_int_converter_malformed[\n123] tests/test_uri_converters.py::test_int_converter_malformed[\r123] tests/test_uri_converters.py::test_int_converter_malformed[\x0b123] tests/test_uri_converters.py::test_int_converter_malformed[\x0c123] tests/test_uri_converters.py::test_int_converter_invalid_config[0] tests/test_uri_converters.py::test_int_converter_invalid_config[-1] tests/test_uri_converters.py::test_int_converter_invalid_config[-10] tests/test_uri_converters.py::test_datetime_converter[07-03-17-%m-%d-%y-expected0] tests/test_uri_converters.py::test_datetime_converter[07-03-17 tests/test_uri_converters.py::test_datetime_converter[2017-07-03T14:30:01Z-%Y-%m-%dT%H:%M:%SZ-expected2] tests/test_uri_converters.py::test_datetime_converter[2017-07-03T14:30:01-%Y-%m-%dT%H:%M:%S-expected3] tests/test_uri_converters.py::test_datetime_converter[2017_19-%Y_%H-expected4] tests/test_uri_converters.py::test_datetime_converter[2017-07-03T14:30:01-%Y-%m-%dT%H:%M:%SZ-None] tests/test_uri_converters.py::test_datetime_converter[ tests/test_uri_converters.py::test_datetime_converter[07 tests/test_uri_converters.py::test_datetime_converter_default_format tests/test_uri_converters.py::test_uuid_converter[ tests/test_uri_templates.py::test_root_path tests/test_uri_templates.py::test_no_vars tests/test_uri_templates.py::test_special_chars tests/test_uri_templates.py::test_single[id] tests/test_uri_templates.py::test_single[id123] tests/test_uri_templates.py::test_single[widget_id] tests/test_uri_templates.py::test_int_converter[/{id:int}] tests/test_uri_templates.py::test_int_converter[/{id:int(3)}] tests/test_uri_templates.py::test_int_converter[/{id:int(min=123)}] tests/test_uri_templates.py::test_int_converter[/{id:int(min=123, tests/test_uri_templates.py::test_int_converter_rejections[/{id:int(2)}] tests/test_uri_templates.py::test_int_converter_rejections[/{id:int(min=124)}] tests/test_uri_templates.py::test_int_converter_rejections[/{id:int(num_digits=3, tests/test_uri_templates.py::test_datetime_converter[/{start_year:int}-to-{timestamp:dt}-/1961-to-1969-07-21T02:56:00Z-dt_expected0] tests/test_uri_templates.py::test_datetime_converter[/{start_year:int}-to-{timestamp:dt("%Y-%m-%d")}-/1961-to-1969-07-21-dt_expected1] tests/test_uri_templates.py::test_datetime_converter[/{start_year:int}/{timestamp:dt("%Y-%m-%d tests/test_uri_templates.py::test_datetime_converter[/{start_year:int}-to-{timestamp:dt("%Y-%m")}-/1961-to-1969-07-21-None] tests/test_uri_templates.py::test_uuid_converter_complex_segment tests/test_uri_templates.py::test_converter_custom[/{food:spam}-/something-expected0] tests/test_uri_templates.py::test_converter_custom[/{food:spam(")")}:{food_too:spam("()")}-/bacon:eggs-expected1] tests/test_uri_templates.py::test_converter_custom[/({food:spam()}){food_too:spam("()")}-/(bacon)eggs-expected2] tests/test_uri_templates.py::test_single_trailing_slash tests/test_uri_templates.py::test_multiple tests/test_uri_templates.py::test_empty_path_component[//] tests/test_uri_templates.py::test_empty_path_component[//begin] tests/test_uri_templates.py::test_empty_path_component[/end//] tests/test_uri_templates.py::test_empty_path_component[/in//side] tests/test_uri_templates.py::test_relative_path[] tests/test_uri_templates.py::test_relative_path[no] tests/test_uri_templates.py::test_relative_path[no/leading_slash] tests/test_uri_templates.py::test_same_level_complex_var[True] tests/test_uri_templates.py::test_same_level_complex_var[False] tests/test_uri_templates.py::test_adding_suffix_routes tests/test_uri_templates.py::test_custom_error_on_suffix_route_not_found tests/test_uri_templates_legacy.py::TestUriTemplates::test_string_type_required[42] tests/test_uri_templates_legacy.py::TestUriTemplates::test_string_type_required[API] tests/test_uri_templates_legacy.py::TestUriTemplates::test_template_must_start_with_slash[this] tests/test_uri_templates_legacy.py::TestUriTemplates::test_template_must_start_with_slash[this/that] tests/test_uri_templates_legacy.py::TestUriTemplates::test_template_may_not_contain_double_slash[//] tests/test_uri_templates_legacy.py::TestUriTemplates::test_template_may_not_contain_double_slash[a//] tests/test_uri_templates_legacy.py::TestUriTemplates::test_template_may_not_contain_double_slash[//b] tests/test_uri_templates_legacy.py::TestUriTemplates::test_template_may_not_contain_double_slash[a//b] tests/test_uri_templates_legacy.py::TestUriTemplates::test_template_may_not_contain_double_slash[a/b//] tests/test_uri_templates_legacy.py::TestUriTemplates::test_template_may_not_contain_double_slash[a/b//c] tests/test_uri_templates_legacy.py::TestUriTemplates::test_root tests/test_uri_templates_legacy.py::TestUriTemplates::test_no_fields[/hello] tests/test_uri_templates_legacy.py::TestUriTemplates::test_no_fields[/hello/world] tests/test_uri_templates_legacy.py::TestUriTemplates::test_no_fields[/hi/there/how/are/you] tests/test_uri_templates_legacy.py::TestUriTemplates::test_one_field tests/test_uri_templates_legacy.py::TestUriTemplates::test_one_field_with_digits tests/test_uri_templates_legacy.py::TestUriTemplates::test_one_field_with_prefixed_digits tests/test_uri_templates_legacy.py::TestUriTemplates::test_two_fields[] tests/test_uri_templates_legacy.py::TestUriTemplates::test_two_fields[/] tests/test_uri_templates_legacy.py::TestUriTemplates::test_three_fields tests/test_uri_templates_legacy.py::TestUriTemplates::test_malformed_field tests/test_utils.py::TestFalconUtils::test_deprecated_decorator tests/test_utils.py::TestFalconUtils::test_http_now tests/test_utils.py::TestFalconUtils::test_dt_to_http tests/test_utils.py::TestFalconUtils::test_http_date_to_dt tests/test_utils.py::TestFalconUtils::test_pack_query_params_none tests/test_utils.py::TestFalconUtils::test_pack_query_params_one tests/test_utils.py::TestFalconUtils::test_pack_query_params_several tests/test_utils.py::TestFalconUtils::test_uri_encode tests/test_utils.py::TestFalconUtils::test_uri_encode_double tests/test_utils.py::TestFalconUtils::test_uri_encode_value tests/test_utils.py::TestFalconUtils::test_uri_decode tests/test_utils.py::TestFalconUtils::test_prop_uri_encode_models_stdlib_quote tests/test_utils.py::TestFalconUtils::test_prop_uri_encode_value_models_stdlib_quote_safe_tilde tests/test_utils.py::TestFalconUtils::test_prop_uri_decode_models_stdlib_unquote_plus tests/test_utils.py::TestFalconUtils::test_unquote_string tests/test_utils.py::TestFalconUtils::test_parse_query_string tests/test_utils.py::TestFalconUtils::test_parse_host tests/test_utils.py::TestFalconUtils::test_get_http_status tests/test_utils.py::test_simulate_request_protocol[https-CONNECT] tests/test_utils.py::test_simulate_request_protocol[https-DELETE] tests/test_utils.py::test_simulate_request_protocol[https-GET] tests/test_utils.py::test_simulate_request_protocol[https-HEAD] tests/test_utils.py::test_simulate_request_protocol[https-OPTIONS] tests/test_utils.py::test_simulate_request_protocol[https-PATCH] tests/test_utils.py::test_simulate_request_protocol[https-POST] tests/test_utils.py::test_simulate_request_protocol[https-PUT] tests/test_utils.py::test_simulate_request_protocol[https-TRACE] tests/test_utils.py::test_simulate_request_protocol[http-CONNECT] tests/test_utils.py::test_simulate_request_protocol[http-DELETE] tests/test_utils.py::test_simulate_request_protocol[http-GET] tests/test_utils.py::test_simulate_request_protocol[http-HEAD] tests/test_utils.py::test_simulate_request_protocol[http-OPTIONS] tests/test_utils.py::test_simulate_request_protocol[http-PATCH] tests/test_utils.py::test_simulate_request_protocol[http-POST] tests/test_utils.py::test_simulate_request_protocol[http-PUT] tests/test_utils.py::test_simulate_request_protocol[http-TRACE] tests/test_utils.py::test_simulate_free_functions[simulate_get] tests/test_utils.py::test_simulate_free_functions[simulate_head] tests/test_utils.py::test_simulate_free_functions[simulate_post] tests/test_utils.py::test_simulate_free_functions[simulate_put] tests/test_utils.py::test_simulate_free_functions[simulate_options] tests/test_utils.py::test_simulate_free_functions[simulate_patch] tests/test_utils.py::test_simulate_free_functions[simulate_delete] tests/test_utils.py::TestFalconTestingUtils::test_path_escape_chars_in_create_environ tests/test_utils.py::TestFalconTestingUtils::test_no_prefix_allowed_for_query_strings_in_create_environ tests/test_utils.py::TestFalconTestingUtils::test_none_header_value_in_create_environ tests/test_utils.py::TestFalconTestingUtils::test_decode_empty_result tests/test_utils.py::TestFalconTestingUtils::test_httpnow_alias_for_backwards_compat tests/test_utils.py::TestFalconTestingUtils::test_default_headers tests/test_utils.py::TestFalconTestingUtils::test_default_headers_with_override tests/test_utils.py::TestFalconTestingUtils::test_status tests/test_utils.py::TestFalconTestingUtils::test_wsgi_iterable_not_closeable tests/test_utils.py::TestFalconTestingUtils::test_path_must_start_with_slash tests/test_utils.py::TestFalconTestingUtils::test_cached_text_in_result tests/test_utils.py::TestFalconTestingUtils::test_simple_resource_body_json_xor tests/test_utils.py::TestFalconTestingUtils::test_query_string tests/test_utils.py::TestFalconTestingUtils::test_query_string_no_question tests/test_utils.py::TestFalconTestingUtils::test_query_string_in_path tests/test_utils.py::TestFalconTestingUtils::test_simulate_json_body[16.0625] tests/test_utils.py::TestFalconTestingUtils::test_simulate_json_body[123456789] tests/test_utils.py::TestFalconTestingUtils::test_simulate_json_body[True] tests/test_utils.py::TestFalconTestingUtils::test_simulate_json_body[] tests/test_utils.py::TestFalconTestingUtils::test_simulate_json_body[I tests/test_utils.py::TestFalconTestingUtils::test_simulate_json_body[document5] tests/test_utils.py::TestFalconTestingUtils::test_simulate_json_body[document6] tests/test_utils.py::TestFalconTestingUtils::test_simulate_json_body[document7] tests/test_utils.py::TestCaseFancyAPI::test_something tests/test_utils.py::TestNoApiClass::test_something tests/test_utils.py::TestSetupApi::test_something tests/test_wsgi.py::TestWSGIServer::test_get tests/test_wsgi.py::TestWSGIServer::test_put tests/test_wsgi.py::TestWSGIServer::test_head_405 tests/test_wsgi.py::TestWSGIServer::test_post tests/test_wsgi.py::TestWSGIServer::test_post_invalid_content_length tests/test_wsgi.py::TestWSGIServer::test_post_read_bounded_stream tests/test_wsgi.py::TestWSGIServer::test_post_read_bounded_stream_no_body tests/test_wsgi_errors.py::TestWSGIError::test_responder_logged_bytestring tests/test_wsgi_interface.py::TestWSGIInterface::test_srmock tests/test_wsgi_interface.py::TestWSGIInterface::test_pep3333 tests/test_wsgiref_inputwrapper_with_size.py::TestWsgiRefInputWrapper::test_resources_can_read_request_stream_during_tests
falcon/routing/static.py falcon/api.py
falcon/routing/static.py falcon/api.py