A minimal low-level HTTP client.
Do one thing, and do it well.
The HTTP Core package provides a minimal low-level HTTP client, which does one thing only. Sending HTTP requests.
It does not provide any high level model abstractions over the API, does not handle redirects, multipart uploads, building authentication headers, transparent HTTP caching, URL parsing, session cookie handling, content or charset decoding, handling JSON, environment based configuration defaults, or any of that Jazz.
Some things HTTP Core does do:
asyncio
and trio
.Python 3.8+
For HTTP/1.1 only support, install with:
$ pip install httpcore
There are also a number of optional extras available...
$ pip install httpcore['asyncio,trio,http2,socks']
Send an HTTP request:
import httpcore
response = httpcore.request("GET", "https://www.example.com/")
print(response)
# <Response [200]>
print(response.status)
# 200
print(response.headers)
# [(b'Accept-Ranges', b'bytes'), (b'Age', b'557328'), (b'Cache-Control', b'max-age=604800'), ...]
print(response.content)
# b'<!doctype html>\n<html>\n<head>\n<title>Example Domain</title>\n\n<meta charset="utf-8"/>\n ...'
The top-level httpcore.request()
function is provided for convenience. In practice whenever you're working with httpcore
you'll want to use the connection pooling functionality that it provides.
import httpcore
http = httpcore.ConnectionPool()
response = http.request("GET", "https://www.example.com/")
Once you're ready to get going, head over to the documentation.
You probably don't want to be using HTTP Core directly. It might make sense if
you're writing something like a proxy service in Python, and you just want
something at the lowest possible level, but more typically you'll want to use
a higher level client library, such as httpx
.
The motivation for httpcore
is:
The httpcore
package has the following dependencies...
h11
certifi
And the following optional extras...
anyio
- Required by pip install httpcore['asyncio']
.trio
- Required by pip install httpcore['trio']
.h2
- Required by pip install httpcore['http2']
.socksio
- Required by pip install httpcore['socks']
.We use SEMVER for our versioning policy.
For changes between package versions please see our project changelog.
We recommend pinning your requirements either the most current major version, or a more specific version range:
pip install 'httpcore==1.*'
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
float("inf")
timeouts in Event.wait
function. (#846)From version 1.0 our async support is now optional, as the package has minimal dependencies by default.
For async support use either pip install 'httpcore[asyncio]'
or pip install 'httpcore[trio]'
.
The project versioning policy is now explicitly governed by SEMVER. See https://semver.org/.
sni_hostname
extension with SOCKS proxy. (#774)Extensions
from Mapping[Str, Any]
to MutableMapping[Str, Any]
. (#762)trace callback
is passed to an asynchronous request or an asynchronous trace callback
is passed to a synchronous request. (#717)socket_options
argument to ConnectionPool
and HTTProxy
classes. (#668)sni_hostname
request extension. (#696)anyio
package. (#692)retries
option to SOCKS proxy classes. (#643)ws
and wss
schemes. Allows us to properly support websocket upgrade connections. (#625)RuntimeError
when closing a connection pool with active connections. Removes some error cases when cancellations are used. (#631)anyio
, so that it's no longer a hard dependancy, and isn't imported if unused. (#639)RuntimeError
if attempting to us UNIX domain sockets on Windows. (#619)h11
0.14. (#579)timeout
configuration. (#506)typing.Optional
for type hints. (#513)trio
map OSError exceptions to ConnectError
. (#543)http://
URLs. (#492)max_connections
becomes optional. (Pull #429)certifi
is now included in the install dependancies. (Pull #428)h2
is now strictly optional. (Pull #428)The 0.14 release is a complete reworking of httpcore
, comprehensively addressing some underlying issues in the connection pooling, as well as substantially redesigning the API to be more user friendly.
Some of the lower-level API design also makes the components more easily testable in isolation, and the package now has 100% test coverage.
See discussion #419 for a little more background.
There's some other neat bits in there too, such as the "trace" extension, which gives a hook into inspecting the internal events that occur during the request/response cycle. This extension is needed for the HTTPX cli, in order to...
Note that curio
support is not currently available in 0.14.0. If you're using httpcore
with curio
please get in touch, so we can assess if we ought to prioritize it as a feature or not.
anyio
as the default backend implementation when running with asyncio
. Resolves some awkward TLS timeout issues.httpcore.SyncConnectionPool(http1=False)
. (Pull #333)select.poll
support. (Pull #331)RemoteProtocolError
where server disconnects without sending a response. (Pull #313)The 0.13 release updates the core API in order to match the HTTPX Transport API, introduced in HTTPX 0.18 onwards.
An example of making requests with the new interface is:
with httpcore.SyncConnectionPool() as http:
status_code, headers, stream, extensions = http.handle_request(
method=b'GET',
url=(b'https', b'example.org', 443, b'/'),
headers=[(b'host', b'example.org'), (b'user-agent', b'httpcore')]
stream=httpcore.ByteStream(b''),
extensions={}
)
body = stream.read()
print(status_code, body)
.request()
method is now handle_request()
. (Pull #296).arequest()
method is now .handle_async_request()
. (Pull #296)headers
argument is no longer optional. (Pull #296)stream
argument is no longer optional. (Pull #296)ext
argument is now named extensions
, and is no longer optional. (Pull #296)"reason"
extension keyword is now named "reason_phrase"
. (Pull #296)"reason_phrase"
and "http_version"
extensions now use byte strings for their values. (Pull #296)httpcore.PlainByteStream()
class becomes httpcore.ByteStream()
. (Pull #296).read()
interface. (Pull #296)asyncio
. (Pull #167)anyio
backend. (Pull #236)Host
header precedence for :authority
in HTTP/2. (Pull #241, #243)asyncio
. (Pull #242, #244)asyncio
SSL warning when using proxy tunneling. (Pull #249)ImportError
occurring on Python 3.9 when using the HTTP/1.1 sync client in a multithreaded context. (Pull #237)trio
. (Pull #225)The Transport API with 0.11.0 has a couple of significant changes.
Firstly we've moved changed the request interface in order to allow extensions, which will later enable us to support features such as trailing headers, HTTP/2 server push, and CONNECT/Upgrade connections.
The interface changes from:
def request(method, url, headers, stream, timeout):
return (http_version, status_code, reason, headers, stream)
To instead including an optional dictionary of extensions on the request and response:
def request(method, url, headers, stream, ext):
return (status_code, headers, stream, ext)
Having an open-ended extensions point will allow us to add later support for various optional features, that wouldn't otherwise be supported without these API changes.
In particular:
Currently extensions are limited to:
timeout
- Optional. Timeout dictionary.http_version
- Optional. Include the HTTP version used on the response.reason
- Optional. Include the reason phrase used on the response. Only valid with HTTP/1.*.See https://github.com/encode/httpx/issues/1274#issuecomment-694884553 for the history behind this.
Secondly, the async version of request
is now namespaced as arequest
.
This allows concrete transports to support both sync and async implementations on the same class.
backend="anyio"
. (Pull #169).request
and .arequest
so implementations can support both sync and async. (Pull #189)max_keepalive_connections
configuration. (Pull #153)max_keepalive_connections
on AsyncHTTPProxy
/SyncHTTPProxy
classes.The most notable change in the 0.10.0 release is that HTTP/2 support is now fully optional.
Use either pip install httpcore
for HTTP/1.1 support only, or pip install httpcore[http2]
for HTTP/1.1 and HTTP/2 support.
local_address=...
support. (Pull #100, #134)PlainByteStream
, IteratorByteStream
, AsyncIteratorByteStream
. The AsyncByteSteam
and SyncByteStream
classes are now pure interface classes. (#133)LocalProtocolError
, RemoteProtocolError
exceptions. (Pull #129)UnsupportedProtocol
exception. (Pull #128).get_connection_info()
method. (Pull #102, #137)max_keepalive
is deprecated in favour of max_keepalive_connections
. (Pull #140)Optional[int]
instead of int
. (Pull #92)Host
and Accept
headers on proxy "CONNECT" requests.httpcore.AsyncByteStream
, httpcore.SyncByteStream
without type conflicts.### Added
TimeoutException
base class.