Skip to content

Commit

Permalink
Merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
ahopkins committed Jun 30, 2024
2 parents 13dc474 + fee71dd commit 121348e
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 36 deletions.
56 changes: 44 additions & 12 deletions sanic/cookies/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ def delete_cookie(
*,
path: str = "/",
domain: Optional[str] = None,
secure: bool = True,
host_prefix: bool = False,
secure_prefix: bool = False,
) -> None:
Expand All @@ -381,6 +382,8 @@ def delete_cookie(
:type path: Optional[str], optional
:param domain: Domain of the cookie, defaults to None
:type domain: Optional[str], optional
:param secure: Whether to delete a secure cookie. Defaults to True.
:param secure: bool
:param host_prefix: Whether to add __Host- as a prefix to the key.
This requires that path="/", domain=None, and secure=True,
defaults to False
Expand All @@ -389,32 +392,61 @@ def delete_cookie(
This requires that secure=True, defaults to False
:type secure_prefix: bool
"""
# remove it from header
if host_prefix and not (secure and path == "/" and domain is None):
raise ServerError(
"Cannot set host_prefix on a cookie without "
"path='/', domain=None, and secure=True"
)
if secure_prefix and not secure:
raise ServerError(
"Cannot set secure_prefix on a cookie without secure=True"
)

cookies: List[Cookie] = self.headers.popall(self.HEADER_KEY, [])
existing_cookie = None
for cookie in cookies:
if (
cookie.key != Cookie.make_key(key, host_prefix, secure_prefix)
or cookie.path != path
or cookie.domain != domain
):
self.headers.add(self.HEADER_KEY, cookie)

elif existing_cookie is None:
existing_cookie = cookie
# This should be removed in v24.3
try:
super().__delitem__(key)
except KeyError:
...

self.add_cookie(
key=key,
value="",
path=path,
domain=domain,
max_age=0,
samesite=None,
host_prefix=host_prefix,
secure_prefix=secure_prefix,
)
if existing_cookie is not None:
# Use all the same values as the cookie to be deleted
# except value="" and max_age=0
self.add_cookie(
key=key,
value="",
path=existing_cookie.path,
domain=existing_cookie.domain,
secure=existing_cookie.secure,
max_age=0,
httponly=existing_cookie.httponly,
partitioned=existing_cookie.partitioned,
samesite=existing_cookie.samesite,
host_prefix=host_prefix,
secure_prefix=secure_prefix,
)
else:
self.add_cookie(
key=key,
value="",
path=path,
domain=domain,
secure=secure,
max_age=0,
samesite=None,
host_prefix=host_prefix,
secure_prefix=secure_prefix,
)


# In v24.3, we should remove this as being a subclass of dict
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,12 @@ def str_to_bool(val: str) -> bool:
"html5tagger>=1.2.1",
"tracerite>=1.0.0",
"typing-extensions>=4.4.0",
"setuptools>=70.1.0",
]

tests_require = [
"sanic-testing>=23.6.0",
"pytest==7.1.*",
"pytest>=8.2.2",
"coverage",
"beautifulsoup4",
"pytest-sanic",
Expand Down
62 changes: 62 additions & 0 deletions tests/test_cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,68 @@ def test_cookie_jar_delete_cookie_encode():
]


def test_cookie_jar_delete_nonsecure_cookie():
headers = Header()
jar = CookieJar(headers)
jar.delete_cookie("foo", domain="example.com", secure=False)

encoded = [cookie.encode("ascii") for cookie in jar.cookies]
assert encoded == [
b'foo=""; Path=/; Domain=example.com; Max-Age=0',
]


def test_cookie_jar_delete_existing_cookie():
headers = Header()
jar = CookieJar(headers)
jar.add_cookie(
"foo", "test", secure=True, domain="example.com", samesite="Strict"
)
jar.delete_cookie("foo", domain="example.com", secure=True)

encoded = [cookie.encode("ascii") for cookie in jar.cookies]
# deletion cookie contains samesite=Strict as was in original cookie
assert encoded == [
b'foo=""; Path=/; Domain=example.com; Max-Age=0; '
b"SameSite=Strict; Secure",
]


def test_cookie_jar_delete_existing_nonsecure_cookie():
headers = Header()
jar = CookieJar(headers)
jar.add_cookie(
"foo", "test", secure=False, domain="example.com", samesite="Strict"
)
jar.delete_cookie("foo", domain="example.com", secure=False)

encoded = [cookie.encode("ascii") for cookie in jar.cookies]
# deletion cookie contains samesite=Strict as was in original cookie
assert encoded == [
b'foo=""; Path=/; Domain=example.com; Max-Age=0; SameSite=Strict',
]


def test_cookie_jar_delete_existing_nonsecure_cookie_bad_prefix():
headers = Header()
jar = CookieJar(headers)
jar.add_cookie(
"foo", "test", secure=False, domain="example.com", samesite="Strict"
)
message = (
"Cannot set host_prefix on a cookie without "
"path='/', domain=None, and secure=True"
)
with pytest.raises(ServerError, match=message):
jar.delete_cookie(
"foo",
domain="example.com",
secure=False,
secure_prefix=True,
host_prefix=True,
)


def test_cookie_jar_old_school_delete_encode():
headers = Header()
jar = CookieJar(headers)
Expand Down
46 changes: 23 additions & 23 deletions tests/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,20 +115,21 @@ def test_url_encoding(client):
@pytest.mark.parametrize(
"content_length",
(
"-50",
"+50",
"5_0",
"50.5",
b"-50",
b"+50",
b"5_0",
b"50.5",
),
)
def test_invalid_content_length(content_length, client):
body = "Hello" * 10
body = b"Hello" * 10
client.send(
f"""
POST /upload HTTP/1.1
content-length: {content_length}
{body}
"""
b"POST /upload HTTP/1.1\r\n"
+ b"content-length: "
+ content_length
+ b"\r\n\r\n"
+ body
+ b"\r\n\r\n"
)

response = client.recv()
Expand All @@ -141,23 +142,22 @@ def test_invalid_content_length(content_length, client):
@pytest.mark.parametrize(
"chunk_length",
(
"-50",
"+50",
"5_0",
"50.5",
b"-50",
b"+50",
b"5_0",
b"50.5",
),
)
def test_invalid_chunk_length(chunk_length, client):
body = "Hello" * 10
body = b"Hello" * 10
client.send(
f"""
POST /upload HTTP/1.1
transfer-encoding: chunked
{chunk_length}
{body}
0
""" # noqa
b"POST /upload HTTP/1.1\r\n"
+ b"transfer-encoding: chunked\r\n\r\n"
+ chunk_length
+ b"\r\n"
+ body
+ b"\r\n"
+ b"0\r\n\r\n"
)

response = client.recv()
Expand Down

0 comments on commit 121348e

Please sign in to comment.