$ pip install httpx
```
-Or, to include the optional HTTP/2 support, use:
+There are also a number of optional dependancies.
+
+For example to include asyncio and HTTP/2 support, use:
```shell
-$ pip install httpx[http2]
+$ pip install 'httpx[asyncio,http2]'
```
HTTPX requires Python 3.8+.
* `h11` - HTTP/1.1 support.
* `certifi` - SSL certificates.
* `idna` - Internationalized domain name support.
-* `sniffio` - Async library autodetection.
As well as these optional installs:
-* `h2` - HTTP/2 support. *(Optional, with `httpx[http2]`)*
-* `socksio` - SOCKS proxy support. *(Optional, with `httpx[socks]`)*
-* `rich` - Rich terminal support. *(Optional, with `httpx[cli]`)*
-* `click` - Command line client support. *(Optional, with `httpx[cli]`)*
-* `brotli` or `brotlicffi` - Decoding for "brotli" compressed responses. *(Optional, with `httpx[brotli]`)*
+* `anyio`, `sniffio` - Async support for `asyncio`. *(Optional, with `httpx['asyncio']`)*
+* `trio`, `sniffio` - Async support for `trio`. *(Optional, with `httpx['trio']`)*
+* `h2` - HTTP/2 support. *(Optional, with `httpx['http2']`)*
+* `socksio` - SOCKS proxy support. *(Optional, with `httpx['socks']`)*
+* `rich` - Rich terminal support. *(Optional, with `httpx['cli']`)*
+* `click` - Command line client support. *(Optional, with `httpx['cli']`)*
+* `brotli` or `brotlicffi` - Decoding for "brotli" compressed responses. *(Optional, with `httpx['brotli']`)*
A huge amount of credit is due to `requests` for the API layout that
much of this work follows, as well as to `urllib3` for plenty of design
If you're working with an async web framework then you'll also want to use an
async client for sending outgoing HTTP requests.
+## Enabling Async support
+
+To enable async support you'll need to install some additional dependencies:
+
+If you're using Python's [standard `asyncio` support](https://docs.python.org/3/library/asyncio.html) then:
+
+```shell
+$ pip install httpx['asyncio']
+```
+
+Or, if you're working with the [`trio` third party package](https://trio.readthedocs.io/en/stable/):
+
+```shell
+$ pip install httpx['trio']
+```
+
+We highly recommend `trio` for async support. The `trio` project [pioneered the principles of structured concurrency](https://en.wikipedia.org/wiki/Structured_concurrency), and has a more carefully constrained API against which to work from.
+
## Making Async requests
To make asynchronous requests, you'll need an `AsyncClient`.
the optional HTTP/2 dependencies...
```shell
-$ pip install httpx[http2]
+$ pip install httpx['http2']
```
And then instantiating a client with HTTP/2 support enabled:
import typing
-import sniffio
-
from .._models import Request, Response
from .._types import AsyncByteStream
from .base import AsyncBaseTransport
def create_event() -> "Event":
+ import sniffio
+
if sniffio.current_async_library() == "trio":
import trio
def map_httpcore_exceptions() -> typing.Iterator[None]:
try:
yield
- except Exception as exc: # noqa: PIE-786
+ except Exception as exc:
mapped_exc = None
for from_exc, to_exc in HTTPCORE_EXC_MAP.items():
retries: int = 0,
socket_options: typing.Optional[typing.Iterable[SOCKET_OPTION]] = None,
) -> None:
+ try:
+ import sniffio # noqa: F401
+ except ImportError: # pragma: nocover
+ raise RuntimeError(
+ "Using httpx in async mode, but neither httpx['asyncio'] or asyncio['trio'] is installed."
+ )
+
ssl_context = create_ssl_context(verify=verify, cert=cert, trust_env=trust_env)
if proxy is None:
from pathlib import Path
from urllib.request import getproxies
-import sniffio
-
from ._types import PrimitiveData
if typing.TYPE_CHECKING: # pragma: no cover
class Timer:
- async def _get_time(self) -> float:
- library = sniffio.current_async_library()
- if library == "trio":
- import trio
-
- return trio.current_time()
- elif library == "curio": # pragma: no cover
- import curio
-
- return typing.cast(float, await curio.clock())
-
- import asyncio
-
- return asyncio.get_event_loop().time()
-
def sync_start(self) -> None:
self.started = time.perf_counter()
async def async_start(self) -> None:
- self.started = await self._get_time()
+ self.started = time.perf_counter()
def sync_elapsed(self) -> float:
now = time.perf_counter()
return now - self.started
async def async_elapsed(self) -> float:
- now = await self._get_time()
+ now = time.perf_counter()
return now - self.started
]
dependencies = [
"certifi",
- "httpcore>=0.18.0,<0.19.0",
+ "httpcore>=1.0.0,<2.0.0",
"idna",
- "sniffio",
]
dynamic = ["readme", "version"]
"rich>=10,<14",
]
http2 = [
- "h2>=3,<5",
+ "httpcore['http2']",
]
socks = [
- "socksio==1.*",
+ "httpcore['socks']",
+]
+asyncio = [
+ "httpcore['asyncio']"
+]
+trio = [
+ "httpcore['trio']"
]
[project.scripts]
# On the other hand, we're not pinning package dependencies, because our tests
# needs to pass with the latest version of the packages.
# Reference: https://github.com/encode/httpx/pull/1721#discussion_r661241588
--e .[brotli,cli,http2,socks]
+-e .[asyncio,trio,brotli,cli,http2,socks]
# Optional charset auto-detection
# Used in our test cases
types-certifi==2021.10.8.2
pytest==7.4.0
ruff==0.0.286
-trio==0.22.2
trio-typing==0.8.0
trustme==1.1.0
uvicorn==0.22.0