mirror of
https://github.com/django/daphne.git
synced 2024-11-21 23:46:33 +03:00
Added support for raw_path in scope. (#268)
As per https://github.com/django/asgiref/pull/92 Required valid URI path fragments to be used in tests: - Test case must ensure paths are correctly quoted before calling run_daphne_request() & co. Co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es>
This commit is contained in:
parent
ffd949f2ce
commit
333f4644d1
|
@ -171,6 +171,7 @@ class WebRequest(http.Request):
|
||||||
),
|
),
|
||||||
"method": self.method.decode("ascii"),
|
"method": self.method.decode("ascii"),
|
||||||
"path": unquote(self.path.decode("ascii")),
|
"path": unquote(self.path.decode("ascii")),
|
||||||
|
"raw_path": self.path,
|
||||||
"root_path": self.root_path,
|
"root_path": self.root_path,
|
||||||
"scheme": self.client_scheme,
|
"scheme": self.client_scheme,
|
||||||
"query_string": self.query_string,
|
"query_string": self.query_string,
|
||||||
|
|
|
@ -75,6 +75,7 @@ class WebSocketProtocol(WebSocketServerProtocol):
|
||||||
{
|
{
|
||||||
"type": "websocket",
|
"type": "websocket",
|
||||||
"path": unquote(self.path.decode("ascii")),
|
"path": unquote(self.path.decode("ascii")),
|
||||||
|
"raw_path": self.path,
|
||||||
"headers": self.clean_headers,
|
"headers": self.clean_headers,
|
||||||
"query_string": self._raw_query_string, # Passed by HTTP protocol
|
"query_string": self._raw_query_string, # Passed by HTTP protocol
|
||||||
"client": self.client_addr,
|
"client": self.client_addr,
|
||||||
|
|
|
@ -32,8 +32,6 @@ class DaphneTestCase(unittest.TestCase):
|
||||||
# Send it the request. We have to do this the long way to allow
|
# Send it the request. We have to do this the long way to allow
|
||||||
# duplicate headers.
|
# duplicate headers.
|
||||||
conn = HTTPConnection(test_app.host, test_app.port, timeout=timeout)
|
conn = HTTPConnection(test_app.host, test_app.port, timeout=timeout)
|
||||||
# Make sure path is urlquoted and add any params
|
|
||||||
path = parse.quote(path)
|
|
||||||
if params:
|
if params:
|
||||||
path += "?" + parse.urlencode(params, doseq=True)
|
path += "?" + parse.urlencode(params, doseq=True)
|
||||||
conn.putrequest(method, path, skip_accept_encoding=True, skip_host=True)
|
conn.putrequest(method, path, skip_accept_encoding=True, skip_host=True)
|
||||||
|
@ -128,8 +126,6 @@ class DaphneTestCase(unittest.TestCase):
|
||||||
# Send it the request. We have to do this the long way to allow
|
# Send it the request. We have to do this the long way to allow
|
||||||
# duplicate headers.
|
# duplicate headers.
|
||||||
conn = HTTPConnection(test_app.host, test_app.port, timeout=timeout)
|
conn = HTTPConnection(test_app.host, test_app.port, timeout=timeout)
|
||||||
# Make sure path is urlquoted and add any params
|
|
||||||
path = parse.quote(path)
|
|
||||||
if params:
|
if params:
|
||||||
path += "?" + parse.urlencode(params, doseq=True)
|
path += "?" + parse.urlencode(params, doseq=True)
|
||||||
conn.putrequest("GET", path, skip_accept_encoding=True, skip_host=True)
|
conn.putrequest("GET", path, skip_accept_encoding=True, skip_host=True)
|
||||||
|
@ -247,12 +243,11 @@ class DaphneTestCase(unittest.TestCase):
|
||||||
# Assert that no other keys are present
|
# Assert that no other keys are present
|
||||||
self.assertEqual(set(), present_keys - required_keys - optional_keys)
|
self.assertEqual(set(), present_keys - required_keys - optional_keys)
|
||||||
|
|
||||||
def assert_valid_path(self, path, request_path):
|
def assert_valid_path(self, path):
|
||||||
"""
|
"""
|
||||||
Checks the path is valid and already url-decoded.
|
Checks the path is valid and already url-decoded.
|
||||||
"""
|
"""
|
||||||
self.assertIsInstance(path, str)
|
self.assertIsInstance(path, str)
|
||||||
self.assertEqual(path, request_path)
|
|
||||||
# Assert that it's already url decoded
|
# Assert that it's already url decoded
|
||||||
self.assertEqual(path, parse.unquote(path))
|
self.assertEqual(path, parse.unquote(path))
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ class TestHTTPRequest(DaphneTestCase):
|
||||||
"http_version",
|
"http_version",
|
||||||
"method",
|
"method",
|
||||||
"path",
|
"path",
|
||||||
|
"raw_path",
|
||||||
"query_string",
|
"query_string",
|
||||||
"headers",
|
"headers",
|
||||||
},
|
},
|
||||||
|
@ -40,7 +41,7 @@ class TestHTTPRequest(DaphneTestCase):
|
||||||
self.assertIsInstance(scope["method"], str)
|
self.assertIsInstance(scope["method"], str)
|
||||||
self.assertEqual(scope["method"], method.upper())
|
self.assertEqual(scope["method"], method.upper())
|
||||||
# Path
|
# Path
|
||||||
self.assert_valid_path(scope["path"], path)
|
self.assert_valid_path(scope["path"])
|
||||||
# HTTP version
|
# HTTP version
|
||||||
self.assertIn(scope["http_version"], ["1.0", "1.1", "1.2"])
|
self.assertIn(scope["http_version"], ["1.0", "1.1", "1.2"])
|
||||||
# Scheme
|
# Scheme
|
||||||
|
@ -134,13 +135,21 @@ class TestHTTPRequest(DaphneTestCase):
|
||||||
self.assert_valid_http_scope(scope, "POST", request_path)
|
self.assert_valid_http_scope(scope, "POST", request_path)
|
||||||
self.assert_valid_http_request_message(messages[0], body=request_body)
|
self.assert_valid_http_request_message(messages[0], body=request_body)
|
||||||
|
|
||||||
|
def test_raw_path(self):
|
||||||
|
"""
|
||||||
|
Tests that /foo%2Fbar produces raw_path and a decoded path
|
||||||
|
"""
|
||||||
|
scope, _ = self.run_daphne_request("GET", "/foo%2Fbar")
|
||||||
|
self.assertEqual(scope["path"], "/foo/bar")
|
||||||
|
self.assertEqual(scope["raw_path"], b"/foo%2Fbar")
|
||||||
|
|
||||||
@given(request_headers=http_strategies.headers())
|
@given(request_headers=http_strategies.headers())
|
||||||
@settings(max_examples=5, deadline=5000)
|
@settings(max_examples=5, deadline=5000)
|
||||||
def test_headers(self, request_headers):
|
def test_headers(self, request_headers):
|
||||||
"""
|
"""
|
||||||
Tests that HTTP header fields are handled as specified
|
Tests that HTTP header fields are handled as specified
|
||||||
"""
|
"""
|
||||||
request_path = "/te st-à/"
|
request_path = parse.quote("/te st-à/")
|
||||||
scope, messages = self.run_daphne_request(
|
scope, messages = self.run_daphne_request(
|
||||||
"OPTIONS", request_path, headers=request_headers
|
"OPTIONS", request_path, headers=request_headers
|
||||||
)
|
)
|
||||||
|
@ -160,7 +169,7 @@ class TestHTTPRequest(DaphneTestCase):
|
||||||
header_name = request_headers[0][0]
|
header_name = request_headers[0][0]
|
||||||
duplicated_headers = [(header_name, header[1]) for header in request_headers]
|
duplicated_headers = [(header_name, header[1]) for header in request_headers]
|
||||||
# Run the request
|
# Run the request
|
||||||
request_path = "/te st-à/"
|
request_path = parse.quote("/te st-à/")
|
||||||
scope, messages = self.run_daphne_request(
|
scope, messages = self.run_daphne_request(
|
||||||
"OPTIONS", request_path, headers=duplicated_headers
|
"OPTIONS", request_path, headers=duplicated_headers
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,14 +24,14 @@ class TestWebsocket(DaphneTestCase):
|
||||||
"""
|
"""
|
||||||
# Check overall keys
|
# Check overall keys
|
||||||
self.assert_key_sets(
|
self.assert_key_sets(
|
||||||
required_keys={"type", "path", "query_string", "headers"},
|
required_keys={"type", "path", "raw_path", "query_string", "headers"},
|
||||||
optional_keys={"scheme", "root_path", "client", "server", "subprotocols"},
|
optional_keys={"scheme", "root_path", "client", "server", "subprotocols"},
|
||||||
actual_keys=scope.keys(),
|
actual_keys=scope.keys(),
|
||||||
)
|
)
|
||||||
# Check that it is the right type
|
# Check that it is the right type
|
||||||
self.assertEqual(scope["type"], "websocket")
|
self.assertEqual(scope["type"], "websocket")
|
||||||
# Path
|
# Path
|
||||||
self.assert_valid_path(scope["path"], path)
|
self.assert_valid_path(scope["path"])
|
||||||
# Scheme
|
# Scheme
|
||||||
self.assertIn(scope.get("scheme", "ws"), ["ws", "wss"])
|
self.assertIn(scope.get("scheme", "ws"), ["ws", "wss"])
|
||||||
if scheme:
|
if scheme:
|
||||||
|
@ -161,7 +161,7 @@ class TestWebsocket(DaphneTestCase):
|
||||||
test_app.add_send_messages([{"type": "websocket.accept"}])
|
test_app.add_send_messages([{"type": "websocket.accept"}])
|
||||||
self.websocket_handshake(
|
self.websocket_handshake(
|
||||||
test_app,
|
test_app,
|
||||||
path=request_path,
|
path=parse.quote(request_path),
|
||||||
params=request_params,
|
params=request_params,
|
||||||
headers=request_headers,
|
headers=request_headers,
|
||||||
)
|
)
|
||||||
|
@ -172,6 +172,19 @@ class TestWebsocket(DaphneTestCase):
|
||||||
)
|
)
|
||||||
self.assert_valid_websocket_connect_message(messages[0])
|
self.assert_valid_websocket_connect_message(messages[0])
|
||||||
|
|
||||||
|
def test_raw_path(self):
|
||||||
|
"""
|
||||||
|
Tests that /foo%2Fbar produces raw_path and a decoded path
|
||||||
|
"""
|
||||||
|
with DaphneTestingInstance() as test_app:
|
||||||
|
test_app.add_send_messages([{"type": "websocket.accept"}])
|
||||||
|
self.websocket_handshake(test_app, path="/foo%2Fbar")
|
||||||
|
# Validate the scope and messages we got
|
||||||
|
scope, _ = test_app.get_received()
|
||||||
|
|
||||||
|
self.assertEqual(scope["path"], "/foo/bar")
|
||||||
|
self.assertEqual(scope["raw_path"], b"/foo%2Fbar")
|
||||||
|
|
||||||
def test_text_frames(self):
|
def test_text_frames(self):
|
||||||
"""
|
"""
|
||||||
Tests we can send and receive text frames.
|
Tests we can send and receive text frames.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user