diff --git a/httpx/_client.py b/httpx/_client.py index 3465a10b75..e9730c93a3 100644 --- a/httpx/_client.py +++ b/httpx/_client.py @@ -559,6 +559,7 @@ def __init__( verify: VerifyTypes = True, cert: CertTypes = None, http2: bool = False, + http2_prior_knowledge: bool = False, proxies: ProxiesTypes = None, mounts: typing.Mapping[str, httpcore.SyncHTTPTransport] = None, timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG, @@ -583,6 +584,9 @@ def __init__( trust_env=trust_env, ) + if http2_prior_knowledge: + http2 = True + if http2: try: import h2 # noqa @@ -1192,6 +1196,7 @@ def __init__( verify: VerifyTypes = True, cert: CertTypes = None, http2: bool = False, + http2_prior_knowledge: bool = False, proxies: ProxiesTypes = None, mounts: typing.Mapping[str, httpcore.AsyncHTTPTransport] = None, timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG, @@ -1216,6 +1221,9 @@ def __init__( trust_env=trust_env, ) + if http2_prior_knowledge: + http2 = True + if http2: try: import h2 # noqa @@ -1239,6 +1247,7 @@ def __init__( verify=verify, cert=cert, http2=http2, + http2_prior_knowledge=http2_prior_knowledge, limits=limits, transport=transport, app=app, @@ -1255,6 +1264,7 @@ def __init__( verify=verify, cert=cert, http2=http2, + http2_prior_knowledge=http2_prior_knowledge, limits=limits, trust_env=trust_env, ) @@ -1271,6 +1281,7 @@ def _init_transport( verify: VerifyTypes = True, cert: CertTypes = None, http2: bool = False, + http2_prior_knowledge: bool = False, limits: Limits = DEFAULT_LIMITS, transport: httpcore.AsyncHTTPTransport = None, app: typing.Callable = None, @@ -1283,7 +1294,12 @@ def _init_transport( return ASGITransport(app=app) return AsyncHTTPTransport( - verify=verify, cert=cert, http2=http2, limits=limits, trust_env=trust_env + verify=verify, + cert=cert, + http2=http2, + http2_prior_knowledge=http2_prior_knowledge, + limits=limits, + trust_env=trust_env, ) def _init_proxy_transport( @@ -1292,6 +1308,7 @@ def _init_proxy_transport( verify: VerifyTypes = True, cert: CertTypes = None, http2: bool = False, + http2_prior_knowledge: bool = False, limits: Limits = DEFAULT_LIMITS, trust_env: bool = True, ) -> httpcore.AsyncHTTPTransport: @@ -1299,6 +1316,7 @@ def _init_proxy_transport( verify=verify, cert=cert, http2=http2, + http2_prior_knowledge=http2_prior_knowledge, limits=limits, trust_env=trust_env, proxy=proxy, diff --git a/httpx/_config.py b/httpx/_config.py index 837519afb5..3175085f51 100644 --- a/httpx/_config.py +++ b/httpx/_config.py @@ -45,9 +45,14 @@ def create_ssl_context( verify: VerifyTypes = True, trust_env: bool = True, http2: bool = False, + http2_prior_knowledge: bool = False, ) -> ssl.SSLContext: return SSLConfig( - cert=cert, verify=verify, trust_env=trust_env, http2=http2 + cert=cert, + verify=verify, + trust_env=trust_env, + http2=http2, + http2_prior_knowledge=http2_prior_knowledge, ).ssl_context @@ -65,11 +70,13 @@ def __init__( verify: VerifyTypes = True, trust_env: bool = True, http2: bool = False, + http2_prior_knowledge: bool = False, ): self.cert = cert self.verify = verify self.trust_env = trust_env self.http2 = http2 + self.http2_prior_knowledge = http2_prior_knowledge self.ssl_context = self.load_ssl_context() def load_ssl_context(self) -> ssl.SSLContext: @@ -79,6 +86,7 @@ def load_ssl_context(self) -> ssl.SSLContext: f"cert={self.cert!r} " f"trust_env={self.trust_env!r} " f"http2={self.http2!r}" + f"http2_prior_knowledge={self.http2_prior_knowledge!r}" ) if self.verify: @@ -162,7 +170,12 @@ def _create_default_ssl_context(self) -> ssl.SSLContext: context.set_ciphers(DEFAULT_CIPHERS) if ssl.HAS_ALPN: - alpn_idents = ["http/1.1", "h2"] if self.http2 else ["http/1.1"] + if self.http2_prior_knowledge: + alpn_idents = ["h2"] + elif self.http2: + alpn_idents = ["http/1.1", "h2"] + else: + alpn_idents = ["http/1.1"] context.set_alpn_protocols(alpn_idents) if hasattr(context, "keylog_filename"): # pragma: nocover (Available in 3.8+) diff --git a/httpx/_transports/default.py b/httpx/_transports/default.py index 84aeb26be8..2500c8a8a5 100644 --- a/httpx/_transports/default.py +++ b/httpx/_transports/default.py @@ -111,6 +111,7 @@ def __init__( verify: VerifyTypes = True, cert: CertTypes = None, http2: bool = False, + http2_prior_knowledge: bool = False, limits: Limits = DEFAULT_LIMITS, trust_env: bool = True, proxy: Proxy = None, @@ -119,7 +120,13 @@ def __init__( retries: int = 0, backend: str = "auto", ) -> None: - ssl_context = create_ssl_context(verify=verify, cert=cert, trust_env=trust_env) + ssl_context = create_ssl_context( + verify=verify, + cert=cert, + trust_env=trust_env, + http2=http2, + http2_prior_knowledge=http2_prior_knowledge, + ) if proxy is None: self._pool = httpcore.AsyncConnectionPool( @@ -128,6 +135,7 @@ def __init__( max_keepalive_connections=limits.max_keepalive_connections, keepalive_expiry=limits.keepalive_expiry, http2=http2, + http2_prior_knowledge=http2_prior_knowledge, uds=uds, local_address=local_address, retries=retries,