Repository: encode/httpx

Issue:
HTTP/2 should be off by default.
So...

I'm super excited that we've got an HTTP/2 implementation in here, but we also need to consider *what default behavior we should be aiming for*, and what we should prioritise.

Our HTTP/2 implementation is neccessarily going to be more complex, and less mature than our HTTP/1.1 implementation. Even if that *wasn't* the case, then HTTP/2 infrastructure that we're connecting too is *more* likely to have implementation issue and quirks than HTTP/1.1 versions.

I think we ought to clearly be *prioritizing for reliablity*, while still supporting users that want the more cutting-edge functionality.

I'd suggest that:

* We ought to have a documentation page on HTTP/2, with a brief overview of the primary differences, and motivation as to *why* user might or might not want to switch HTTP/2 support on.
* We ought to tidy up our interface for switching between HTTP versions.

We currently have this...

```python
client = Client(http_versions=["HTTP/1.1", "HTTP/2"])  # Really clunky
client = Client(http_versions=["HTTP/1.1"]) 
client = Client(http_versions=["HTTP/2"])  # Doesn't really make sense - you *might* still end up with an HTTP/1.1 connection.
```

I think we should just switch to...

```python
client = Client(http_2=True)
client = Client(http_2=False)
```

Furthermore, I think the default ought to be false. There's no point in exposing our users to this class of issues https://github.com/encode/httpx/issues?q=is%3Aissue+is%3Aopen+label%3Ahttp%2F2 *as our default behaviour*, but we can still make it easy for our users to upgrade to the HTTP/2 implementation.

Discussion:
tomchristie: > I suppose this moves us forward relative to minimal dependencies, eg we’ll now be able to not require h2 unless users want to use HTTP/2?

Ah yeah I'd forgotten about that. We *can also* make that switch here, yup.
I guess we would drop `h2` out of our default install, and into `extra_requires`, so...

`pip install httpx[h2]`

And a check on the client for "if http_2 is True and h2 is not installed then error".
florimondmanca: > We can also make that switch here, yup.

I’d rather we deal with it later, this PR is quite a big chunk already. :-)
tomchristie: Good call.
tomchristie: Should we use `httpx.Client(http_2=True)` or `httpx.Client(http2=True)`?

I think the later is probably neater, right?

Patch:
diff --git a/docs/advanced.md b/docs/advanced.md
index d087bd2..9b1502f 100644
--- a/docs/advanced.md
+++ b/docs/advanced.md
@@ -141,20 +141,6 @@ make modifications before sending the request.
 <Response [200 OK]>
 ```
 
-## Specify the version of the HTTP protocol
-
-One can set the version of the HTTP protocol for the client in case you want to make the requests using a specific version.
-
-For example:
-
-```python
-async with httpx.Client(http_versions=["HTTP/1.1"]) as h11_client:
-    h11_response = await h11_client.get("https://myserver.com")
-
-async with httpx.Client(http_versions=["HTTP/2"]) as h2_client:
-    h2_response = await h2_client.get("https://myserver.com")
-```
-
 ## .netrc Support
 
 HTTPX supports .netrc file. In `trust_env=True` cases, if auth parameter is
@@ -367,7 +353,7 @@ More specifically, if a tuple is used as a value, it must have between 2 and 3 e
 - The first element is an optional file name which can be set to `None`.
 - The second element may be a file-like object or a string which will be automatically
 encoded in UTF-8.
-- An optional third element can be used to specify the 
+- An optional third element can be used to specify the
 [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_Types)
 of the file being uploaded. If not specified HTTPX will attempt to guess the MIME type based
 on the file name, with unknown file extensions defaulting to "application/octet-stream".
diff --git a/docs/http2.md b/docs/http2.md
new file mode 100644
index 0000000..66d835d
--- /dev/null
+++ b/docs/http2.md
@@ -0,0 +1,60 @@
+# HTTP/2
+
+HTTP/2 is a major new iteration of the HTTP protocol, that provides a far more
+efficient transport, with potential performance benefits. HTTP/2 does not change
+the core semantics of the request or response, but alters the way that data is
+sent to and from the server.
+
+Rather that the text format that HTTP/1.1 uses, HTTP/2 is a binary format.
+The binary format provides full request and response multiplexing, and efficient
+compression of HTTP headers. The stream multiplexing means that where HTTP/1.1
+requires one TCP stream for each concurrent request, HTTP/2 allows a single TCP
+stream to handle multiple concurrent requests.
+
+HTTP/2 also provides support for functionality such as response prioritization,
+and server push.
+
+For a comprehensive guide to HTTP/2 you may want to check out "[HTTP2 Explained](https://http2-explained.haxx.se/content/en/)".
+
+## Enabling HTTP/2
+
+The HTTPX client provides provisional HTTP/2 support.
+
+HTTP/2 support is not enabled by default, because HTTP/1.1 is a mature,
+battle-hardened transport layer. With HTTP/2 being newer and significantly more
+complex, our implementation should be considered a less robust option at this
+point in time.
+
+However, if you're issuing highly concurrent requests you might want to consider
+trying out our HTTP/2 support. You can do so by instantiating a client with
+HTTP/2 support enabled:
+
+```python
+client = httpx.Client(http_2=True)
+...
+```
+
+You can also instantiate a client as a context manager, to ensure that all
+HTTP connections are nicely scoped, and will be closed once the context block
+is exited.
+
+```python
+async with httpx.Client(http_2=True) as client:
+    ...
+```
+
+## Inspecting the HTTP version
+
+Enabling HTTP/2 support on the client does not *necessarily* mean that your
+requests and responses will be transported over HTTP/2, since both the client
+*and* the server need to support HTTP/2. If you connect to a server that only
+supports HTTP/1.1 the client will use a standard HTTP/1.1 connection instead.
+
+You can determine which version of the HTTP protocol was used by examining
+the `.http_version` property on the response.
+
+```python
+client = httpx.Client(http_2=True)
+response = await client.get(...)
+print(response.http_version)  # "HTTP/1.0", "HTTP/1.1", or "HTTP/2".
+```
diff --git a/docs/index.md b/docs/index.md
index 846d58a..c233494 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -64,7 +64,7 @@ HTTPX is a high performance asynchronous HTTP client, that builds on the
 well-established usability of `requests`, and gives you:
 
 * A broadly requests-compatible API.
-* HTTP/2 and HTTP/1.1 support.
+* HTTP/1.1 and [HTTP/2 support](http2.md).
 * Ability to [make requests directly to ASGI applications](advanced.md#calling-into-python-web-apps).
 * Strict timeouts everywhere.
 * Fully type annotated.
@@ -92,7 +92,8 @@ Plus all the standard features of `requests`...
 
 For a run-through of all the basics, head over to the [QuickStart](quickstart.md).
 
-For more advanced topics, see the [Advanced Usage](advanced.md) section.
+For more advanced topics, see the [Advanced Usage](advanced.md) section,
+or the [HTTP/2](http2.md) section.
 
 The [Developer Interface](api.md) provides a comprehensive API reference.
 
diff --git a/httpx/__init__.py b/httpx/__init__.py
index bda76ae..0910545 100644
--- a/httpx/__init__.py
+++ b/httpx/__init__.py
@@ -12,8 +12,6 @@ from .concurrency.base import (
 from .config import (
     USER_AGENT,
     CertTypes,
-    HTTPVersionConfig,
-    HTTPVersionTypes,
     PoolLimits,
     SSLConfig,
     TimeoutConfig,
@@ -118,8 +116,6 @@ __all__ = [
     "StatusCode",
     "codes",
     "TimeoutTypes",
-    "HTTPVersionTypes",
-    "HTTPVersionConfig",
     "AuthTypes",
     "Cookies",
     "CookieTypes",
diff --git a/httpx/api.py b/httpx/api.py
index 2ea1be6..893c3e7 100644
--- a/httpx/api.py
+++ b/httpx/api.py
@@ -81,11 +81,7 @@ async def request(
     ```
     """
     async with Client(
-        http_versions=["HTTP/1.1"],
-        cert=cert,
-        verify=verify,
-        timeout=timeout,
-        trust_env=trust_env,
+        cert=cert, verify=verify, timeout=timeout, trust_env=trust_env,
     ) as client:
         return await client.request(
             method=method,
diff --git a/httpx/client.py b/httpx/client.py
index 1fe4f6c..28aa176 100644
--- a/httpx/client.py
+++ b/httpx/client.py
@@ -12,7 +12,6 @@ from .config import (
     DEFAULT_POOL_LIMITS,
     DEFAULT_TIMEOUT_CONFIG,
     CertTypes,
-    HTTPVersionTypes,
     PoolLimits,
     TimeoutTypes,
     VerifyTypes,
@@ -79,8 +78,8 @@ class Client:
     to authenticate the client. Either a path to an SSL certificate file, or
     two-tuple of (certificate file, key file), or a three-tuple of (certificate
     file, key file, password).
-    * **http_versions** - *(optional)* A list of strings of HTTP protocol
-    versions to use when sending requests. eg. `http_versions=["HTTP/1.1"]`
+    * **http_2** - *(optional)* A boolean indicating if HTTP/2 support should be
+    enabled. Defaults to `False`.
     * **proxies** - *(optional)* A dictionary mapping HTTP protocols to proxy
     URLs.
     * **timeout** - *(optional)* The timeout configuration to use when sending
@@ -111,7 +110,7 @@ class Client:
         cookies: CookieTypes = None,
         verify: VerifyTypes = True,
         cert: CertTypes = None,
-        http_versions: HTTPVersionTypes = None,
+        http_2: bool = False,
         proxies: ProxiesTypes = None,
         timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
         pool_limits: PoolLimits = DEFAULT_POOL_LIMITS,
@@ -134,7 +133,7 @@ class Client:
                 verify=verify,
                 cert=cert,
                 timeout=timeout,
-                http_versions=http_versions,
+                http_2=http_2,
                 pool_limits=pool_limits,
                 backend=backend,
                 trust_env=trust_env,
@@ -167,7 +166,7 @@ class Client:
             verify=verify,
             cert=cert,
             timeout=timeout,
-            http_versions=http_versions,
+            http_2=http_2,
             pool_limits=pool_limits,
             backend=backend,
             trust_env=trust_env,
@@ -833,13 +832,13 @@ def _proxies_to_dispatchers(
     verify: VerifyTypes,
     cert: typing.Optional[CertTypes],
     timeout: TimeoutTypes,
-    http_versions: typing.Optional[HTTPVersionTypes],
+    http_2: bool,
     pool_limits: PoolLimits,
     backend: ConcurrencyBackend,
     trust_env: bool,
 ) -> typing.Dict[str, Dispatcher]:
     def _proxy_from_url(url: URLTypes) -> Dispatcher:
-        nonlocal verify, cert, timeout, http_versions, pool_limits, backend, trust_env
+        nonlocal verify, cert, timeout, http_2, pool_limits, backend, trust_env
         url = URL(url)
         if url.scheme in ("http", "https"):
             return HTTPProxy(
@@ -850,7 +849,7 @@ def _proxies_to_dispatchers(
                 pool_limits=pool_limits,
                 backend=backend,
                 trust_env=trust_env,
-                http_versions=http_versions,
+                http_2=http_2,
             )
         raise ValueError(f"Unknown proxy for {url!r}")
 
diff --git a/httpx/config.py b/httpx/config.py
index a32ae84..cace3c2 100644
--- a/httpx/config.py
+++ b/httpx/config.py
@@ -13,15 +13,10 @@ VerifyTypes = typing.Union[str, bool, ssl.SSLContext]
 TimeoutTypes = typing.Union[
     float, typing.Tuple[float, float, float, float], "TimeoutConfig"
 ]
-HTTPVersionTypes = typing.Union[
-    str, typing.List[str], typing.Tuple[str], "HTTPVersionConfig"
-]
 
 
 USER_AGENT = f"python-httpx/{__version__}"
 
-HTTP_VERSIONS_TO_ALPN_IDENTIFIERS = {"HTTP/1.1": "http/1.1", "HTTP/2": "h2"}
-
 DEFAULT_CIPHERS = ":".join(
     [
         "ECDHE+AESGCM",
@@ -91,43 +86,35 @@ class SSLConfig:
             return self
         return SSLConfig(cert=cert, verify=verify)
 
-    def load_ssl_context(
-        self, http_versions: "HTTPVersionConfig" = None
-    ) -> ssl.SSLContext:
-        http_versions = HTTPVersionConfig() if http_versions is None else http_versions
-
+    def load_ssl_context(self, http_2: bool = False) -> ssl.SSLContext:
         logger.trace(
             f"load_ssl_context "
             f"verify={self.verify!r} "
             f"cert={self.cert!r} "
             f"trust_env={self.trust_env!r} "
-            f"http_versions={http_versions!r}"
+            f"http_2={http_2!r}"
         )
 
         if self.ssl_context is None:
             self.ssl_context = (
-                self.load_ssl_context_verify(http_versions=http_versions)
+                self.load_ssl_context_verify(http_2=http_2)
                 if self.verify
-                else self.load_ssl_context_no_verify(http_versions=http_versions)
+                else self.load_ssl_context_no_verify(http_2=http_2)
             )
 
         assert self.ssl_context is not None
         return self.ssl_context
 
-    def load_ssl_context_no_verify(
-        self, http_versions: "HTTPVersionConfig"
-    ) -> ssl.SSLContext:
+    def load_ssl_context_no_verify(self, http_2: bool = False) -> ssl.SSLContext:
         """
         Return an SSL context for unverified connections.
         """
-        context = self._create_default_ssl_context(http_versions=http_versions)
+        context = self._create_default_ssl_context(http_2=http_2)
         context.verify_mode = ssl.CERT_NONE
         context.check_hostname = False
         return context
 
-    def load_ssl_context_verify(
-        self, http_versions: "HTTPVersionConfig"
-    ) -> ssl.SSLContext:
+    def load_ssl_context_verify(self, http_2: bool = False) -> ssl.SSLContext:
         """
         Return an SSL context for verified connections.
         """
@@ -146,7 +133,7 @@ class SSLConfig:
                 "invalid path: {}".format(self.verify)
             )
 
-        context = self._create_default_ssl_context(http_versions=http_versions)
+        context = self._create_default_ssl_context(http_2=http_2)
         context.verify_mode = ssl.CERT_REQUIRED
         context.check_hostname = True
 
@@ -175,9 +162,7 @@ class SSLConfig:
 
         return context
 
-    def _create_default_ssl_context(
-        self, http_versions: "HTTPVersionConfig"
-    ) -> ssl.SSLContext:
+    def _create_default_ssl_context(self, http_2: bool) -> ssl.SSLContext:
         """
         Creates the default SSLContext object that's used for both verified
         and unverified connections.
@@ -191,7 +176,8 @@ class SSLConfig:
         context.set_ciphers(DEFAULT_CIPHERS)
 
         if ssl.HAS_ALPN:
-            context.set_alpn_protocols(http_versions.alpn_identifiers)
+            alpn_idents = ["http/1.1", "h2"] if http_2 else ["http/1.1"]
+            context.set_alpn_protocols(alpn_idents)
 
         if hasattr(context, "keylog_filename"):
             keylogfile = os.environ.get("SSLKEYLOGFILE")
@@ -288,52 +274,6 @@ class TimeoutConfig:
         )
 
 
-class HTTPVersionConfig:
-    """
-    Configure which HTTP protocol versions are supported.
-    """
-
-    def __init__(self, http_versions: HTTPVersionTypes = None):
-        if http_versions is None:
-            http_versions = ["HTTP/1.1", "HTTP/2"]
-
-        if isinstance(http_versions, str):
-            self.http_versions = {http_versions.upper()}
-        elif isinstance(http_versions, HTTPVersionConfig):
-            self.http_versions = http_versions.http_versions
-        elif isinstance(http_versions, typing.Iterable):
-            self.http_versions = {
-                version.upper() if isinstance(version, str) else version
-                for version in http_versions
-            }
-        else:
-            raise TypeError(
-                "HTTP version should be a string or list of strings, "
-                f"but got {type(http_versions)}"
-            )
-
-        for version in self.http_versions:
-            if version not in ("HTTP/1.1", "HTTP/2"):
-                raise ValueError(f"Unsupported HTTP version {version!r}.")
-
-        if not self.http_versions:
-            raise ValueError("HTTP versions cannot be an empty list.")
-
-    @property
-    def alpn_identifiers(self) -> typing.List[str]:
-        """
-        Returns a list of supported ALPN identifiers. (One or more of "http/1.1", "h2").
-        """
-        return [
-            HTTP_VERSIONS_TO_ALPN_IDENTIFIERS[version] for version in self.http_versions
-        ]
-
-    def __repr__(self) -> str:
-        class_name = self.__class__.__name__
-        value = sorted(list(self.http_versions))
-        return f"{class_name}({value!r})"
-
-
 class PoolLimits:
     """
     Limits on the number of connections in a connection pool.
diff --git a/httpx/dispatch/connection.py b/httpx/dispatch/connection.py
index 6694caa..0f05b2e 100644
--- a/httpx/dispatch/connection.py
+++ b/httpx/dispatch/connection.py
@@ -7,8 +7,6 @@ from ..concurrency.base import ConcurrencyBackend
 from ..config import (
     DEFAULT_TIMEOUT_CONFIG,
     CertTypes,
-    HTTPVersionConfig,
-    HTTPVersionTypes,
     SSLConfig,
     TimeoutConfig,
     TimeoutTypes,
@@ -35,7 +33,7 @@ class HTTPConnection(Dispatcher):
         cert: CertTypes = None,
         trust_env: bool = None,
         timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
-        http_versions: HTTPVersionTypes = None,
+        http_2: bool = False,
         backend: ConcurrencyBackend = None,
         release_func: typing.Optional[ReleaseCallback] = None,
         uds: typing.Optional[str] = None,
@@ -43,7 +41,7 @@ class HTTPConnection(Dispatcher):
         self.origin = Origin(origin) if isinstance(origin, str) else origin
         self.ssl = SSLConfig(cert=cert, verify=verify, trust_env=trust_env)
         self.timeout = TimeoutConfig(timeout)
-        self.http_versions = HTTPVersionConfig(http_versions)
+        self.http_2 = http_2
         self.backend = AsyncioBackend() if backend is None else backend
         self.release_func = release_func
         self.uds = uds
@@ -119,9 +117,7 @@ class HTTPConnection(Dispatcher):
             return None
 
         # Run the SSL loading in a threadpool, since it may make disk accesses.
-        return await self.backend.run_in_threadpool(
-            ssl.load_ssl_context, self.http_versions
-        )
+        return await self.backend.run_in_threadpool(ssl.load_ssl_context, self.http_2)
 
     async def close(self) -> None:
         logger.trace("close_connection")
diff --git a/httpx/dispatch/connection_pool.py b/httpx/dispatch/connection_pool.py
index 3217330..fc44c41 100644
--- a/httpx/dispatch/connection_pool.py
+++ b/httpx/dispatch/connection_pool.py
@@ -6,7 +6,6 @@ from ..config import (
     DEFAULT_POOL_LIMITS,
     DEFAULT_TIMEOUT_CONFIG,
     CertTypes,
-    HTTPVersionTypes,
     PoolLimits,
     TimeoutConfig,
     TimeoutTypes,
@@ -88,7 +87,7 @@ class ConnectionPool(Dispatcher):
         trust_env: bool = None,
         timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
         pool_limits: PoolLimits = DEFAULT_POOL_LIMITS,
-        http_versions: HTTPVersionTypes = None,
+        http_2: bool = False,
         backend: ConcurrencyBackend = None,
         uds: typing.Optional[str] = None,
     ):
@@ -96,7 +95,7 @@ class ConnectionPool(Dispatcher):
         self.cert = cert
         self.timeout = TimeoutConfig(timeout)
         self.pool_limits = pool_limits
-        self.http_versions = http_versions
+        self.http_2 = http_2
         self.is_closed = False
         self.trust_env = trust_env
         self.uds = uds
@@ -150,7 +149,7 @@ class ConnectionPool(Dispatcher):
                 verify=self.verify,
                 cert=self.cert,
                 timeout=self.timeout,
-                http_versions=self.http_versions,
+                http_2=self.http_2,
                 backend=self.backend,
                 release_func=self.release_connection,
                 trust_env=self.trust_env,
diff --git a/httpx/dispatch/proxy_http.py b/httpx/dispatch/proxy_http.py
index 13eb423..c51c009 100644
--- a/httpx/dispatch/proxy_http.py
+++ b/httpx/dispatch/proxy_http.py
@@ -8,7 +8,6 @@ from ..config import (
     DEFAULT_POOL_LIMITS,
     DEFAULT_TIMEOUT_CONFIG,
     CertTypes,
-    HTTPVersionTypes,
     PoolLimits,
     SSLConfig,
     TimeoutTypes,
@@ -47,7 +46,7 @@ class HTTPProxy(ConnectionPool):
         trust_env: bool = None,
         timeout: TimeoutTypes = DEFAULT_TIMEOUT_CONFIG,
         pool_limits: PoolLimits = DEFAULT_POOL_LIMITS,
-        http_versions: HTTPVersionTypes = None,
+        http_2: bool = False,
         backend: ConcurrencyBackend = None,
     ):
 
@@ -58,7 +57,7 @@ class HTTPProxy(ConnectionPool):
             pool_limits=pool_limits,
             backend=backend,
             trust_env=trust_env,
-            http_versions=http_versions,
+            http_2=http_2,
         )
 
         self.proxy_url = URL(proxy_url)
@@ -134,7 +133,7 @@ class HTTPProxy(ConnectionPool):
             cert=self.cert,
             timeout=self.timeout,
             backend=self.backend,
-            http_versions=["HTTP/1.1"],  # Short-lived 'connection'
+            http_2=False,  # Short-lived 'connection'
             trust_env=self.trust_env,
             release_func=self.release_connection,
         )
diff --git a/mkdocs.yml b/mkdocs.yml
index 0ddd8c8..a2a733c 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -12,6 +12,7 @@ nav:
     - Introduction: 'index.md'
     - QuickStart: 'quickstart.md'
     - Advanced Usage: 'advanced.md'
+    - HTTP/2 Support: 'http2.md'
     - Environment Variables: 'environment_variables.md'
     - Requests Compatibility: 'compatibility.md'
     - Developer Interface: 'api.md'


Test patch:
diff --git a/tests/client/test_proxies.py b/tests/client/test_proxies.py
index fc1e57a..ede15a8 100644
--- a/tests/client/test_proxies.py
+++ b/tests/client/test_proxies.py
@@ -36,7 +36,6 @@ def test_proxies_has_same_properties_as_dispatch():
         cert="/path/to/cert",
         trust_env=False,
         timeout=30,
-        http_versions=["HTTP/1.1"],
     )
     pool = client.dispatch
     proxy = client.proxies["all"]
@@ -49,7 +48,6 @@ def test_proxies_has_same_properties_as_dispatch():
         "cert",
         "timeout",
         "pool_limits",
-        "http_versions",
         "backend",
     ]:
         assert getattr(pool, prop) == getattr(proxy, prop)
diff --git a/tests/dispatch/test_http2.py b/tests/dispatch/test_http2.py
index 0c8c917..86dcc8f 100644
--- a/tests/dispatch/test_http2.py
+++ b/tests/dispatch/test_http2.py
@@ -27,7 +27,7 @@ def app(request):
 async def test_http2_get_request():
     backend = MockHTTP2Backend(app=app)
 
-    async with Client(backend=backend) as client:
+    async with Client(backend=backend, http_2=True) as client:
         response = await client.get("http://example.org")
 
     assert response.status_code == 200
@@ -38,7 +38,7 @@ async def test_http2_get_request():
 async def test_http2_post_request():
     backend = MockHTTP2Backend(app=app)
 
-    async with Client(backend=backend) as client:
+    async with Client(backend=backend, http_2=True) as client:
         response = await client.post("http://example.org", data=b"<data>")
 
     assert response.status_code == 200
@@ -54,7 +54,7 @@ async def test_http2_large_post_request():
     backend = MockHTTP2Backend(app=app)
 
     data = b"a" * 100000
-    async with Client(backend=backend) as client:
+    async with Client(backend=backend, http_2=True) as client:
         response = await client.post("http://example.org", data=data)
     assert response.status_code == 200
     assert json.loads(response.content) == {
@@ -68,7 +68,7 @@ async def test_http2_large_post_request():
 async def test_http2_multiple_requests():
     backend = MockHTTP2Backend(app=app)
 
-    async with Client(backend=backend) as client:
+    async with Client(backend=backend, http_2=True) as client:
         response_1 = await client.get("http://example.org/1")
         response_2 = await client.get("http://example.org/2")
         response_3 = await client.get("http://example.org/3")
@@ -91,7 +91,7 @@ async def test_http2_reconnect():
     """
     backend = MockHTTP2Backend(app=app)
 
-    async with Client(backend=backend) as client:
+    async with Client(backend=backend, http_2=True) as client:
         response_1 = await client.get("http://example.org/1")
         backend.server.close_connection = True
         response_2 = await client.get("http://example.org/2")
@@ -106,7 +106,7 @@ async def test_http2_reconnect():
 async def test_http2_settings_in_handshake(backend):
     backend = MockHTTP2Backend(app=app, backend=backend)
 
-    async with Client(backend=backend) as client:
+    async with Client(backend=backend, http_2=True) as client:
         await client.get("http://example.org")
 
     h2_conn = backend.server.conn
@@ -139,7 +139,7 @@ async def test_http2_settings_in_handshake(backend):
 
 
 async def test_http2_live_request(backend):
-    async with Client(backend=backend) as client:
+    async with Client(backend=backend, http_2=True) as client:
         try:
             resp = await client.get("https://nghttp2.org/httpbin/anything")
         except Timeout:
diff --git a/tests/test_concurrency.py b/tests/test_concurrency.py
index da43987..52828da 100644
--- a/tests/test_concurrency.py
+++ b/tests/test_concurrency.py
@@ -1,7 +1,7 @@
 import pytest
 import trio
 
-from httpx import AsyncioBackend, HTTPVersionConfig, SSLConfig, TimeoutConfig
+from httpx import AsyncioBackend, SSLConfig, TimeoutConfig
 from httpx.concurrency.trio import TrioBackend
 from tests.concurrency import run_concurrently
 
@@ -40,7 +40,7 @@ async def read_response(stream, timeout: float, should_contain: bytes) -> bytes:
     ],
 )
 async def test_start_tls_on_tcp_socket_stream(https_server, backend, get_cipher):
-    ctx = SSLConfig().load_ssl_context_no_verify(HTTPVersionConfig())
+    ctx = SSLConfig().load_ssl_context_no_verify()
     timeout = TimeoutConfig(5)
 
     stream = await backend.open_tcp_stream(
@@ -72,7 +72,7 @@ async def test_start_tls_on_tcp_socket_stream(https_server, backend, get_cipher)
     ],
 )
 async def test_start_tls_on_uds_socket_stream(https_uds_server, backend, get_cipher):
-    ctx = SSLConfig().load_ssl_context_no_verify(HTTPVersionConfig())
+    ctx = SSLConfig().load_ssl_context_no_verify()
     timeout = TimeoutConfig(5)
 
     stream = await backend.open_uds_stream(
diff --git a/tests/test_config.py b/tests/test_config.py
index 6f8d808..1835ec7 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -118,46 +118,6 @@ def test_ssl_repr():
     assert repr(ssl) == "SSLConfig(cert=None, verify=False)"
 
 
-def test_http_versions_repr():
-    http_versions = httpx.HTTPVersionConfig()
-    assert repr(http_versions) == "HTTPVersionConfig(['HTTP/1.1', 'HTTP/2'])"
-
-
-def test_http_versions_from_string():
-    http_versions = httpx.HTTPVersionConfig("HTTP/1.1")
-    assert repr(http_versions) == "HTTPVersionConfig(['HTTP/1.1'])"
-
-
-def test_http_versions_from_list():
-    http_versions = httpx.HTTPVersionConfig(["http/1.1"])
-    assert repr(http_versions) == "HTTPVersionConfig(['HTTP/1.1'])"
-
-
-def test_http_versions_from_config():
-    http_versions = httpx.HTTPVersionConfig(httpx.HTTPVersionConfig("HTTP/1.1"))
-    assert repr(http_versions) == "HTTPVersionConfig(['HTTP/1.1'])"
-
-
-def test_invalid_http_version():
-    with pytest.raises(ValueError):
-        httpx.HTTPVersionConfig("HTTP/9")
-
-
-def test_invalid_http_version_type():
-    with pytest.raises(TypeError):
-        httpx.HTTPVersionConfig(123)
-
-
-def test_invalid_http_version_list_type():
-    with pytest.raises(ValueError):
-        httpx.HTTPVersionConfig([123])
-
-
-def test_empty_http_version():
-    with pytest.raises(ValueError):
-        httpx.HTTPVersionConfig([])
-
-
 def test_limits_repr():
     limits = httpx.PoolLimits(hard_limit=100)
     assert repr(limits) == "PoolLimits(soft_limit=None, hard_limit=100)"
diff --git a/tests/test_multipart.py b/tests/test_multipart.py
index 3936a05..b5e2290 100644
--- a/tests/test_multipart.py
+++ b/tests/test_multipart.py
@@ -10,7 +10,6 @@ from httpx import (
     CertTypes,
     Client,
     Dispatcher,
-    HTTPVersionTypes,
     Request,
     Response,
     TimeoutTypes,
@@ -26,7 +25,6 @@ class MockDispatch(Dispatcher):
         verify: VerifyTypes = None,
         cert: CertTypes = None,
         timeout: TimeoutTypes = None,
-        http_versions: HTTPVersionTypes = None,
     ) -> Response:
         content = await request.read()
         return Response(200, content=content)