Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/requests/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class _ValidatedRequest(PreparedRequest):

HeadersType: TypeAlias = Mapping[str, str | bytes] | None

CookiesType: TypeAlias = RequestsCookieJar | Mapping[str, str]
CookiesType: TypeAlias = RequestsCookieJar | Mapping[str, str | None]

# Building blocks for FilesType
_FileName: TypeAlias = str | None
Expand Down
18 changes: 10 additions & 8 deletions src/requests/cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import calendar
import copy
import time
from collections.abc import Iterator, MutableMapping
from collections.abc import Iterator, Mapping, MutableMapping
from http.cookiejar import Cookie, CookieJar, CookiePolicy
from typing import TYPE_CHECKING, Any, TypeVar, overload

Expand Down Expand Up @@ -562,22 +562,22 @@ def morsel_to_cookie(morsel: Morsel[Any]) -> Cookie:

@overload
def cookiejar_from_dict(
cookie_dict: dict[str, str] | None,
cookie_dict: Mapping[str, str | None] | None,
cookiejar: None = None,
overwrite: bool = True,
) -> RequestsCookieJar: ...


@overload
def cookiejar_from_dict(
cookie_dict: dict[str, str] | None,
cookie_dict: Mapping[str, str | None] | None,
cookiejar: _CookieJarT,
overwrite: bool = True,
) -> _CookieJarT: ...


def cookiejar_from_dict(
cookie_dict: dict[str, str] | None,
cookie_dict: Mapping[str, str | None] | None,
cookiejar: CookieJar | None = None,
overwrite: bool = True,
) -> CookieJar:
Expand All @@ -594,15 +594,17 @@ def cookiejar_from_dict(

if cookie_dict is not None:
names_from_jar = [cookie.name for cookie in cookiejar]
for name in cookie_dict:
if overwrite or (name not in names_from_jar):
cookiejar.set_cookie(create_cookie(name, cookie_dict[name]))
for name, value in cookie_dict.items():
if value is None:
remove_cookie_by_name(cookiejar, name)
elif overwrite or (name not in names_from_jar):
cookiejar.set_cookie(create_cookie(name, value))

return cookiejar


def merge_cookies(
cookiejar: CookieJar, cookies: dict[str, str] | CookieJar | None
cookiejar: CookieJar, cookies: Mapping[str, str | None] | CookieJar | None
) -> CookieJar:
"""Add cookies to cookiejar and returns a merged CookieJar.

Expand Down
14 changes: 7 additions & 7 deletions src/requests/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,14 +523,14 @@ def prepare_request(self, request: Request) -> PreparedRequest:

cookies = request.cookies or {}

# Bootstrap CookieJar.
if not isinstance(cookies, cookielib.CookieJar):
cookies = cookiejar_from_dict(cookies)

# Merge with session cookies
merged_cookies = merge_cookies(
merge_cookies(RequestsCookieJar(), self.cookies), cookies
)
merged_cookies = merge_cookies(RequestsCookieJar(), self.cookies)
if isinstance(cookies, cookielib.CookieJar):
merged_cookies = merge_cookies(merged_cookies, cookies)
else:
merged_cookies = cookiejar_from_dict(
cookies, cookiejar=merged_cookies, overwrite=True
)

# Set environment's basic authentication if not explicitly set.
auth = request.auth
Expand Down
12 changes: 12 additions & 0 deletions tests/test_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,18 @@ def test_request_cookie_overrides_session_cookie(self, httpbin):
# Session cookie should not be modified
assert s.cookies["foo"] == "bar"

def test_request_cookie_none_removes_session_cookie(self):
s = requests.session()
s.cookies["foo"] = "bar"
req = requests.Request(
"GET", "http://example.com/", cookies={"foo": None, "baz": "qux"}
)

prepared = s.prepare_request(req)

assert prepared.headers["Cookie"] == "baz=qux"
assert s.cookies["foo"] == "bar"

def test_request_cookies_not_persisted(self, httpbin):
s = requests.session()
s.get(httpbin("cookies"), cookies={"foo": "baz"})
Expand Down