Skip to content

Commit

Permalink
feat(testing): add raw_path to ASGI scope (#2331)
Browse files Browse the repository at this point in the history
* style (testing): fix errors in gates

* docs (newsfragment): add newsfragment

* refactor (testing): refactor asgi test

* test (test_recipes): update test for asgi scope

* docs(testing): clean up the docs, tests and notes before merging

* docs(testing): add a versionadded note, improve impl

---------

Co-authored-by: Vytautas Liuolia <vytautas.liuolia@gmail.com>
  • Loading branch information
aarcex3 and vytas7 authored Dec 8, 2024
1 parent 5f295ab commit 11076b8
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 15 deletions.
5 changes: 5 additions & 0 deletions docs/_newsfragments/2262.newandimproved.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Similar to :func:`~falcon.testing.create_environ`,
the :func:`~falcon.testing.create_scope` testing helper now preserves the raw URI path,
and propagates it to the created ASGI connection scope as the ``raw_path`` byte string
(according to the `ASGI specification
<https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope>`__).
9 changes: 8 additions & 1 deletion falcon/testing/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -974,10 +974,16 @@ def create_scope(
iterable yielding a series of two-member (*name*, *value*)
iterables. Each pair of items provides the name and value
for the 'Set-Cookie' header.
.. versionadded:: 4.1
The raw (i.e., not URL-decoded) version of the provided `path` is now
preserved in the returned scope as the ``raw_path`` byte string.
According to the ASGI specification, ``raw_path`` **does not include**
any query string.
"""

http_version = _fixup_http_version(http_version)

raw_path, _, _ = path.partition('?')
path = uri.decode(path, unquote_plus=False)

# NOTE(kgriffs): Handles both None and ''
Expand All @@ -995,6 +1001,7 @@ def create_scope(
'http_version': http_version,
'method': method.upper(),
'path': path,
'raw_path': raw_path.encode(),
'query_string': query_string_bytes,
}

Expand Down
18 changes: 18 additions & 0 deletions tests/asgi/test_testing_asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,21 @@ def test_immediate_disconnect():

with pytest.raises(ConnectionError):
client.simulate_get('/', asgi_disconnect_ttl=0)


@pytest.mark.parametrize(
'path, expected',
[
('/cache/http%3A%2F%2Ffalconframework.org/status', True),
(
'/cache/http%3A%2F%2Ffalconframework.org/status?param1=value1&param2=value2',
False,
),
],
)
def test_create_scope_preserve_raw_path(path, expected):
scope = testing.create_scope(path=path)
if expected:
assert scope['raw_path'] == path.encode()
else:
assert scope['raw_path'] != path.encode()
22 changes: 8 additions & 14 deletions tests/test_recipes.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,29 +115,23 @@ def test_optional_indent(self, util):


class TestRawURLPath:
def path_extras(self, asgi, url):
if asgi:
return {'raw_path': url.encode()}
return None

def test_raw_path(self, asgi, app_kind, util):
recipe = util.load_module(
'raw_url_path', parent_dir='examples/recipes', suffix=app_kind
)

# TODO(vytas): Improve TestClient to automatically add ASGI raw_path
# (as it does for WSGI): GH #2262.

url1 = '/cache/http%3A%2F%2Ffalconframework.org'
result1 = falcon.testing.simulate_get(
recipe.app, url1, extras=self.path_extras(asgi, url1)
)
result1 = falcon.testing.simulate_get(recipe.app, url1)
assert result1.status_code == 200
assert result1.json == {'url': 'http://falconframework.org'}

scope1 = falcon.testing.create_scope(url1)
assert scope1['raw_path'] == url1.encode()

url2 = '/cache/http%3A%2F%2Ffalconframework.org/status'
result2 = falcon.testing.simulate_get(
recipe.app, url2, extras=self.path_extras(asgi, url2)
)
result2 = falcon.testing.simulate_get(recipe.app, url2)
assert result2.status_code == 200
assert result2.json == {'cached': True}

scope2 = falcon.testing.create_scope(url2)
assert scope2['raw_path'] == url2.encode()

0 comments on commit 11076b8

Please sign in to comment.