)
from ._urls import URL
from ._utils import (
- guess_json_utf,
is_known_encoding,
normalize_header_key,
normalize_header_value,
raise HTTPStatusError(message, request=request, response=self)
def json(self, **kwargs: typing.Any) -> typing.Any:
- if self.charset_encoding is None and self.content and len(self.content) > 3:
- encoding = guess_json_utf(self.content)
- if encoding is not None:
- return jsonlib.loads(self.content.decode(encoding), **kwargs)
- return jsonlib.loads(self.text, **kwargs)
+ return jsonlib.loads(self.content, **kwargs)
@property
def cookies(self) -> "Cookies":
return f'{name}="{value}"'.encode()
-# Null bytes; no need to recreate these on each call to guess_json_utf
-_null = b"\x00"
-_null2 = _null * 2
-_null3 = _null * 3
-
-
-def guess_json_utf(data: bytes) -> typing.Optional[str]:
- # JSON always starts with two ASCII characters, so detection is as
- # easy as counting the nulls and from their location and count
- # determine the encoding. Also detect a BOM, if present.
- sample = data[:4]
- if sample in (codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE):
- return "utf-32" # BOM included
- if sample[:3] == codecs.BOM_UTF8:
- return "utf-8-sig" # BOM included, MS style (discouraged)
- if sample[:2] in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE):
- return "utf-16" # BOM included
- nullcount = sample.count(_null)
- if nullcount == 0:
- return "utf-8"
- if nullcount == 2:
- if sample[::2] == _null2: # 1st and 3rd are null
- return "utf-16-be"
- if sample[1::2] == _null2: # 2nd and 4th are null
- return "utf-16-le"
- # Did not detect 2 valid UTF-16 ascii-range characters
- if nullcount == 3:
- if sample[:3] == _null3:
- return "utf-32-be"
- if sample[1:] == _null3:
- return "utf-32-le"
- # Did not detect a valid UTF-32 ascii-range character
- return None
-
-
def get_ca_bundle_from_env() -> typing.Optional[str]:
if "SSL_CERT_FILE" in os.environ:
ssl_file = Path(os.environ["SSL_CERT_FILE"])
+import json
import logging
import os
import random
URLPattern,
get_ca_bundle_from_env,
get_environment_proxies,
- guess_json_utf,
is_https_redirect,
obfuscate_sensitive_headers,
parse_header_links,
),
)
def test_encoded(encoding):
- data = "{}".encode(encoding)
- assert guess_json_utf(data) == encoding
+ content = '{"abc": 123}'.encode(encoding)
+ response = httpx.Response(200, content=content)
+ assert response.json() == {"abc": 123}
def test_bad_utf_like_encoding():
- assert guess_json_utf(b"\x00\x00\x00\x00") is None
+ content = b"\x00\x00\x00\x00"
+ response = httpx.Response(200, content=content)
+ with pytest.raises(json.decoder.JSONDecodeError):
+ response.json()
@pytest.mark.parametrize(
),
)
def test_guess_by_bom(encoding, expected):
- data = "\ufeff{}".encode(encoding)
- assert guess_json_utf(data) == expected
+ content = '\ufeff{"abc": 123}'.encode(encoding)
+ response = httpx.Response(200, content=content)
+ assert response.json() == {"abc": 123}
@pytest.mark.parametrize(