Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
update(refactoring): add a decode method and test for non latin chara…
…cters
  • Loading branch information
kalingth committed Jul 26, 2024
commit c5c0aee8a047597b9c21a1ba78ccf2832168f090
40 changes: 32 additions & 8 deletions src/requests/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,37 @@ def init_per_thread_state(self):
self._thread_local.num_401_calls = None

@staticmethod
def encode_to_bytes(data, encoding="latin-1"):
def _encode_data(data, encoding="latin-1"):
"""
This function encodes input data to bytes using the specified
encoding (default is Latin-1). It returns the encoded data as bytes.
:rtype: bytes
"""
if type(data) == bytes:
if type(data) is bytes:
return data
str_data = str(data)
return str_data.encode(encoding)
try:
return str_data.encode(encoding)
except UnicodeEncodeError:
warnings.warn(
"This data will be encoded with UTF-8 because the provided "
"encoding could not handle some characters.",
category=UnicodeWarning,
)
return HTTPDigestAuth._encode_data(data, 'utf-8')


@staticmethod
def _decode_data(data, encoding="utf-8"):
"""
This function decodes input data from bytes using the specified
encoding (default is UTF-8). It returns the decoded data as a string.
:rtype: str
"""
if type(data) is not bytes:
return data
return data.decode(encoding)


def build_digest_header(self, method, url):
"""
Expand Down Expand Up @@ -198,9 +219,9 @@ def sha512_utf8(x):
if p_parsed.query:
path += f"?{p_parsed.query}"

username = self.encode_to_bytes(self.username)
realm = self.encode_to_bytes(realm)
password = self.encode_to_bytes(self.password)
username = self._encode_data(self.username)
realm = self._encode_data(realm)
password = self._encode_data(self.password)

A1 = b':'.join([username, realm, password])
A2 = f"{method}:{path}"
Expand Down Expand Up @@ -234,9 +255,12 @@ def sha512_utf8(x):
self._thread_local.last_nonce = nonce

# XXX should the partial digests be encoded too?
decoded_username = self._decode_data(username)
decoded_realm = self._decode_data(realm)
decoded_nonce = self._decode_data(nonce)
base = (
f'username="{self.username}", realm="{realm}", nonce="{nonce}", '
f'uri="{path}", response="{respdig}"'
f'username="{decoded_username}", realm="{decoded_realm}", '
f'nonce="{decoded_nonce}", uri="{path}", response="{respdig}"'
)
if opaque:
base += f', opaque="{opaque}"'
Expand Down
14 changes: 10 additions & 4 deletions tests/test_auth.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
from requests.auth import HTTPDigestAuth

# from requests.auth import HTTPDigestAuth
from src.requests.auth import HTTPDigestAuth

class TestDigestAuth:

Expand All @@ -11,11 +11,17 @@ def _build_a_digest_auth(self, user, password):
auth._thread_local.chal["nonce"] = 'chips'
return auth.build_digest_header('GET', 'https://www.example.com/')

@pytest.mark.parametrize("username, password", [("spam", "ham")])
@pytest.mark.parametrize(
"username, password",
(
("spam", "ham"),
("имя", "пароль"),
)
)
def test_digestauth_encode_consistency(self, username, password):
auth = username, password
str_auth = self._build_a_digest_auth(*auth)
bauth = username.encode('utf-8'), password.encode('utf-8')
bin_auth = self._build_a_digest_auth(*bauth)
assert str(str_auth) == str(bin_auth)
assert str_auth == bin_auth