httpx2 2.0.0b1__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {httpx2-2.0.0b1 → httpx2-2.2.0}/CHANGELOG.md +26 -0
- httpx2-2.2.0/LICENSE.md +13 -0
- httpx2-2.2.0/PKG-INFO +200 -0
- httpx2-2.2.0/README.md +140 -0
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/__init__.py +17 -16
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_auth.py +9 -29
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_client.py +28 -83
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_config.py +3 -13
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_content.py +1 -3
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_decoders.py +41 -23
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_exceptions.py +2 -8
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_main.py +9 -29
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_models.py +15 -54
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_multipart.py +10 -31
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_transports/asgi.py +3 -7
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_transports/base.py +2 -6
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_transports/default.py +2 -4
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_transports/wsgi.py +1 -4
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_types.py +2 -6
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_urlparse.py +11 -36
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_urls.py +6 -21
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_utils.py +2 -8
- {httpx2-2.0.0b1 → httpx2-2.2.0}/pyproject.toml +13 -9
- httpx2-2.0.0b1/PKG-INFO +0 -215
- httpx2-2.0.0b1/README.md +0 -147
- {httpx2-2.0.0b1 → httpx2-2.2.0}/.gitignore +0 -0
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/__version__.py +0 -0
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_api.py +0 -0
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_status_codes.py +0 -0
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_transports/__init__.py +0 -0
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/_transports/mock.py +0 -0
- {httpx2-2.0.0b1 → httpx2-2.2.0}/httpx2/py.typed +0 -0
|
@@ -4,6 +4,32 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
+
## 2.2.0 (May 16th, 2026)
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
* Handle multi-frame zstd streams split across chunks. ([#946](https://github.com/pydantic/httpx2/pull/946))
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
* Lazily import the `_main` CLI module to speed up `import httpx2`. ([#947](https://github.com/pydantic/httpx2/pull/947))
|
|
16
|
+
|
|
17
|
+
## 2.1.0 (May 15th, 2026)
|
|
18
|
+
|
|
19
|
+
### Removed
|
|
20
|
+
|
|
21
|
+
* Drop support for Python 3.9. ([#208](https://github.com/pydantic/httpx2/pull/208))
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
* Add support for Python 3.14. ([#208](https://github.com/pydantic/httpx2/pull/208))
|
|
26
|
+
* Use stdlib `compression.zstd` for Zstd decompression on Python 3.14+; fall back to the `zstandard` package on older versions. ([#932](https://github.com/pydantic/httpx2/pull/932))
|
|
27
|
+
* Bundle `LICENSE.md` in the sdist. ([#938](https://github.com/pydantic/httpx2/pull/938))
|
|
28
|
+
|
|
29
|
+
## 2.0.0
|
|
30
|
+
|
|
31
|
+
Official first release of `httpx2`. No changes since `2.0.0b1`.
|
|
32
|
+
|
|
7
33
|
## 2.0.0b1
|
|
8
34
|
|
|
9
35
|
First release of `httpx2`, a fork of [`httpx`](https://github.com/encode/httpx) maintained by Pydantic. Forked from `httpx 0.28.1` (commit [`b5addb6`](https://github.com/encode/httpx/commit/b5addb6)).
|
httpx2-2.2.0/LICENSE.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright © 2026 to present Pydantic Services Inc. and individual contributors.
|
|
2
|
+
Copyright © 2019, [Encode OSS Ltd](https://www.encode.io/).
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
8
|
+
|
|
9
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
10
|
+
|
|
11
|
+
* Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
12
|
+
|
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
httpx2-2.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: httpx2
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: The next generation HTTP client.
|
|
5
|
+
Project-URL: Changelog, https://github.com/pydantic/httpx2/blob/main/src/httpx2/CHANGELOG.md
|
|
6
|
+
Project-URL: Homepage, https://github.com/pydantic/httpx2
|
|
7
|
+
Project-URL: Source, https://github.com/pydantic/httpx2
|
|
8
|
+
Author-email: Tom Christie <tom@tomchristie.com>
|
|
9
|
+
Maintainer-email: "Pydantic Services Inc." <engineering@pydantic.dev>
|
|
10
|
+
License-Expression: BSD-3-Clause
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Web Environment
|
|
13
|
+
Classifier: Framework :: AsyncIO
|
|
14
|
+
Classifier: Framework :: Trio
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
25
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Requires-Dist: anyio
|
|
28
|
+
Requires-Dist: certifi
|
|
29
|
+
Requires-Dist: httpcore2==2.2.0
|
|
30
|
+
Requires-Dist: idna
|
|
31
|
+
Provides-Extra: brotli
|
|
32
|
+
Requires-Dist: brotli; (platform_python_implementation == 'CPython') and extra == 'brotli'
|
|
33
|
+
Requires-Dist: brotlicffi; (platform_python_implementation != 'CPython') and extra == 'brotli'
|
|
34
|
+
Provides-Extra: cli
|
|
35
|
+
Requires-Dist: click==8.*; extra == 'cli'
|
|
36
|
+
Requires-Dist: pygments==2.*; extra == 'cli'
|
|
37
|
+
Requires-Dist: rich<15,>=10; extra == 'cli'
|
|
38
|
+
Provides-Extra: http2
|
|
39
|
+
Requires-Dist: h2<5,>=3; extra == 'http2'
|
|
40
|
+
Provides-Extra: socks
|
|
41
|
+
Requires-Dist: socksio==1.*; extra == 'socks'
|
|
42
|
+
Provides-Extra: zstd
|
|
43
|
+
Requires-Dist: zstandard>=0.18.0; (python_version <= '3.13') and extra == 'zstd'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
<h1 align="center">HTTPX2</h1>
|
|
47
|
+
|
|
48
|
+
<p align="center"><em>A next-generation HTTP client for Python.</em></p>
|
|
49
|
+
|
|
50
|
+
<p align="center">
|
|
51
|
+
<a href="https://github.com/pydantic/httpx2/actions"><img src="https://github.com/pydantic/httpx2/workflows/Test%20Suite/badge.svg" alt="Test Suite"></a>
|
|
52
|
+
<a href="https://pypi.org/project/httpx2/"><img src="https://badge.fury.io/py/httpx2.svg" alt="Package version"></a>
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
HTTPX2 is a fully featured HTTP client library for Python 3. It includes **an integrated command line client**, has support for both **HTTP/1.1 and HTTP/2**, and provides both **sync and async APIs**.
|
|
56
|
+
|
|
57
|
+
> [!NOTE]
|
|
58
|
+
> HTTPX2 is a continuation of the wonderful work started by [@lovelydinosaur](https://github.com/lovelydinosaur) and the broader HTTPX community. We're enormously grateful for everything that has gone into HTTPX over the years - it has been a foundational piece of the modern Python ecosystem, and this project would not exist without it.
|
|
59
|
+
>
|
|
60
|
+
> With HTTPX itself seeing limited activity recently, Pydantic is picking up stewardship under the HTTPX2 name so that users have a reliably maintained path forward - including timely security updates for a library that sits in the critical path of so many production systems. Our aim is to honour the original project's design, keep it stable for everyone relying on it, and continue evolving it carefully. Thank you to [@lovelydinosaur](https://github.com/lovelydinosaur) and every past contributor for laying such a strong foundation. 💙
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
Install HTTPX2 using pip:
|
|
65
|
+
|
|
66
|
+
```shell
|
|
67
|
+
pip install httpx2
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Now, let's get started:
|
|
71
|
+
|
|
72
|
+
```pycon
|
|
73
|
+
>>> import httpx2
|
|
74
|
+
>>> r = httpx2.get('https://www.example.org/')
|
|
75
|
+
>>> r
|
|
76
|
+
<Response [200 OK]>
|
|
77
|
+
>>> r.status_code
|
|
78
|
+
200
|
|
79
|
+
>>> r.headers['content-type']
|
|
80
|
+
'text/html; charset=UTF-8'
|
|
81
|
+
>>> r.text
|
|
82
|
+
'<!doctype html>\n<html>\n<head>\n<title>Example Domain</title>...'
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Or, using the command-line client.
|
|
86
|
+
|
|
87
|
+
```shell
|
|
88
|
+
pip install 'httpx2[cli]' # The command line client is an optional dependency.
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Which now allows us to use HTTPX2 directly from the command-line:
|
|
92
|
+
|
|
93
|
+
```shell
|
|
94
|
+
httpx2 --help
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Features
|
|
98
|
+
|
|
99
|
+
HTTPX2 builds on the well-established usability of `requests`, and gives you:
|
|
100
|
+
|
|
101
|
+
* A broadly [requests-compatible API](https://httpx2.pydantic.dev/compatibility/).
|
|
102
|
+
* An integrated command-line client.
|
|
103
|
+
* HTTP/1.1 [and HTTP/2 support](https://httpx2.pydantic.dev/http2/).
|
|
104
|
+
* Standard synchronous interface, but with [async support if you need it](https://httpx2.pydantic.dev/async/).
|
|
105
|
+
* Ability to make requests directly to [WSGI applications](https://httpx2.pydantic.dev/advanced/transports/#wsgi-transport) or [ASGI applications](https://httpx2.pydantic.dev/advanced/transports/#asgi-transport).
|
|
106
|
+
* Strict timeouts everywhere.
|
|
107
|
+
* Fully type annotated.
|
|
108
|
+
* 100% test coverage.
|
|
109
|
+
|
|
110
|
+
Plus all the standard features of `requests`...
|
|
111
|
+
|
|
112
|
+
* International Domains and URLs
|
|
113
|
+
* Keep-Alive & Connection Pooling
|
|
114
|
+
* Sessions with Cookie Persistence
|
|
115
|
+
* Browser-style SSL Verification
|
|
116
|
+
* Basic/Digest Authentication
|
|
117
|
+
* Elegant Key/Value Cookies
|
|
118
|
+
* Automatic Decompression
|
|
119
|
+
* Automatic Content Decoding
|
|
120
|
+
* Unicode Response Bodies
|
|
121
|
+
* Multipart File Uploads
|
|
122
|
+
* HTTP(S) Proxy Support
|
|
123
|
+
* Connection Timeouts
|
|
124
|
+
* Streaming Downloads
|
|
125
|
+
* .netrc Support
|
|
126
|
+
* Chunked Requests
|
|
127
|
+
|
|
128
|
+
## Installation
|
|
129
|
+
|
|
130
|
+
Install with pip:
|
|
131
|
+
|
|
132
|
+
```shell
|
|
133
|
+
pip install httpx2
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Or, to include the optional HTTP/2 support, use:
|
|
137
|
+
|
|
138
|
+
```shell
|
|
139
|
+
pip install httpx2[http2]
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
HTTPX2 requires Python 3.10+.
|
|
143
|
+
|
|
144
|
+
## Documentation
|
|
145
|
+
|
|
146
|
+
Project documentation is available at [https://httpx2.pydantic.dev/](https://httpx2.pydantic.dev/).
|
|
147
|
+
|
|
148
|
+
For a run-through of all the basics, head over to the [QuickStart](https://httpx2.pydantic.dev/quickstart/).
|
|
149
|
+
|
|
150
|
+
For more advanced topics, see the [Advanced Usage](https://httpx2.pydantic.dev/advanced/) section, the [async support](https://httpx2.pydantic.dev/async/) section, or the [HTTP/2](https://httpx2.pydantic.dev/http2/) section.
|
|
151
|
+
|
|
152
|
+
The [Developer Interface](https://httpx2.pydantic.dev/api/) provides a comprehensive API reference.
|
|
153
|
+
|
|
154
|
+
To find out about tools that integrate with HTTPX, see [Third Party Packages](https://httpx2.pydantic.dev/third_party_packages/).
|
|
155
|
+
|
|
156
|
+
## Contribute
|
|
157
|
+
|
|
158
|
+
If you want to contribute with HTTPX2 check out the [Contributing Guide](https://httpx2.pydantic.dev/contributing/) to learn how to start.
|
|
159
|
+
|
|
160
|
+
## Dependencies
|
|
161
|
+
|
|
162
|
+
The HTTPX2 project relies on these excellent libraries:
|
|
163
|
+
|
|
164
|
+
* `httpcore2` - The underlying transport implementation for `httpx2`.
|
|
165
|
+
* `h11` - HTTP/1.1 support.
|
|
166
|
+
* `anyio` - Structured concurrency primitives, used to support both `asyncio` and `trio`.
|
|
167
|
+
* `certifi` - SSL certificates.
|
|
168
|
+
* `idna` - Internationalized domain name support.
|
|
169
|
+
|
|
170
|
+
As well as these optional installs:
|
|
171
|
+
|
|
172
|
+
* `h2` - HTTP/2 support. *(Optional, with `httpx2[http2]`)*
|
|
173
|
+
* `socksio` - SOCKS proxy support. *(Optional, with `httpx2[socks]`)*
|
|
174
|
+
* `rich` - Rich terminal support. *(Optional, with `httpx2[cli]`)*
|
|
175
|
+
* `click` - Command line client support. *(Optional, with `httpx2[cli]`)*
|
|
176
|
+
* `brotli` or `brotlicffi` - Decoding for "brotli" compressed responses. *(Optional, with `httpx2[brotli]`)*
|
|
177
|
+
* `zstandard` - Decoding for "zstd" compressed responses on Python 3.13 and below. *(Optional, with `httpx2[zstd]`. On Python 3.14+, `zstd` is supported natively via the stdlib [`compression.zstd`](https://docs.python.org/3/library/compression.zstd.html) module.)*
|
|
178
|
+
|
|
179
|
+
A huge amount of credit is due to `requests` for the API layout that
|
|
180
|
+
much of this work follows, as well as to `urllib3` for plenty of design
|
|
181
|
+
inspiration around the lower-level networking details.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
<p align="center"><i>HTTPX2 is <a href="https://github.com/pydantic/httpx2/blob/main/LICENSE.md">BSD licensed</a> code.<br/>Designed & crafted with care.</i><br/>— 🦋 —</p>
|
|
186
|
+
|
|
187
|
+
## Release Information
|
|
188
|
+
|
|
189
|
+
### Fixed
|
|
190
|
+
|
|
191
|
+
* Handle multi-frame zstd streams split across chunks. ([#946](https://github.com/pydantic/httpx2/pull/946))
|
|
192
|
+
|
|
193
|
+
### Changed
|
|
194
|
+
|
|
195
|
+
* Lazily import the `_main` CLI module to speed up `import httpx2`. ([#947](https://github.com/pydantic/httpx2/pull/947))
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
[Full changelog](https://github.com/pydantic/httpx2/blob/main/src/httpx2/CHANGELOG.md)
|
httpx2-2.2.0/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<h1 align="center">HTTPX2</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center"><em>A next-generation HTTP client for Python.</em></p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://github.com/pydantic/httpx2/actions"><img src="https://github.com/pydantic/httpx2/workflows/Test%20Suite/badge.svg" alt="Test Suite"></a>
|
|
7
|
+
<a href="https://pypi.org/project/httpx2/"><img src="https://badge.fury.io/py/httpx2.svg" alt="Package version"></a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
HTTPX2 is a fully featured HTTP client library for Python 3. It includes **an integrated command line client**, has support for both **HTTP/1.1 and HTTP/2**, and provides both **sync and async APIs**.
|
|
11
|
+
|
|
12
|
+
> [!NOTE]
|
|
13
|
+
> HTTPX2 is a continuation of the wonderful work started by [@lovelydinosaur](https://github.com/lovelydinosaur) and the broader HTTPX community. We're enormously grateful for everything that has gone into HTTPX over the years - it has been a foundational piece of the modern Python ecosystem, and this project would not exist without it.
|
|
14
|
+
>
|
|
15
|
+
> With HTTPX itself seeing limited activity recently, Pydantic is picking up stewardship under the HTTPX2 name so that users have a reliably maintained path forward - including timely security updates for a library that sits in the critical path of so many production systems. Our aim is to honour the original project's design, keep it stable for everyone relying on it, and continue evolving it carefully. Thank you to [@lovelydinosaur](https://github.com/lovelydinosaur) and every past contributor for laying such a strong foundation. 💙
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
Install HTTPX2 using pip:
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
pip install httpx2
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Now, let's get started:
|
|
26
|
+
|
|
27
|
+
```pycon
|
|
28
|
+
>>> import httpx2
|
|
29
|
+
>>> r = httpx2.get('https://www.example.org/')
|
|
30
|
+
>>> r
|
|
31
|
+
<Response [200 OK]>
|
|
32
|
+
>>> r.status_code
|
|
33
|
+
200
|
|
34
|
+
>>> r.headers['content-type']
|
|
35
|
+
'text/html; charset=UTF-8'
|
|
36
|
+
>>> r.text
|
|
37
|
+
'<!doctype html>\n<html>\n<head>\n<title>Example Domain</title>...'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or, using the command-line client.
|
|
41
|
+
|
|
42
|
+
```shell
|
|
43
|
+
pip install 'httpx2[cli]' # The command line client is an optional dependency.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Which now allows us to use HTTPX2 directly from the command-line:
|
|
47
|
+
|
|
48
|
+
```shell
|
|
49
|
+
httpx2 --help
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
HTTPX2 builds on the well-established usability of `requests`, and gives you:
|
|
55
|
+
|
|
56
|
+
* A broadly [requests-compatible API](https://httpx2.pydantic.dev/compatibility/).
|
|
57
|
+
* An integrated command-line client.
|
|
58
|
+
* HTTP/1.1 [and HTTP/2 support](https://httpx2.pydantic.dev/http2/).
|
|
59
|
+
* Standard synchronous interface, but with [async support if you need it](https://httpx2.pydantic.dev/async/).
|
|
60
|
+
* Ability to make requests directly to [WSGI applications](https://httpx2.pydantic.dev/advanced/transports/#wsgi-transport) or [ASGI applications](https://httpx2.pydantic.dev/advanced/transports/#asgi-transport).
|
|
61
|
+
* Strict timeouts everywhere.
|
|
62
|
+
* Fully type annotated.
|
|
63
|
+
* 100% test coverage.
|
|
64
|
+
|
|
65
|
+
Plus all the standard features of `requests`...
|
|
66
|
+
|
|
67
|
+
* International Domains and URLs
|
|
68
|
+
* Keep-Alive & Connection Pooling
|
|
69
|
+
* Sessions with Cookie Persistence
|
|
70
|
+
* Browser-style SSL Verification
|
|
71
|
+
* Basic/Digest Authentication
|
|
72
|
+
* Elegant Key/Value Cookies
|
|
73
|
+
* Automatic Decompression
|
|
74
|
+
* Automatic Content Decoding
|
|
75
|
+
* Unicode Response Bodies
|
|
76
|
+
* Multipart File Uploads
|
|
77
|
+
* HTTP(S) Proxy Support
|
|
78
|
+
* Connection Timeouts
|
|
79
|
+
* Streaming Downloads
|
|
80
|
+
* .netrc Support
|
|
81
|
+
* Chunked Requests
|
|
82
|
+
|
|
83
|
+
## Installation
|
|
84
|
+
|
|
85
|
+
Install with pip:
|
|
86
|
+
|
|
87
|
+
```shell
|
|
88
|
+
pip install httpx2
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Or, to include the optional HTTP/2 support, use:
|
|
92
|
+
|
|
93
|
+
```shell
|
|
94
|
+
pip install httpx2[http2]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
HTTPX2 requires Python 3.10+.
|
|
98
|
+
|
|
99
|
+
## Documentation
|
|
100
|
+
|
|
101
|
+
Project documentation is available at [https://httpx2.pydantic.dev/](https://httpx2.pydantic.dev/).
|
|
102
|
+
|
|
103
|
+
For a run-through of all the basics, head over to the [QuickStart](https://httpx2.pydantic.dev/quickstart/).
|
|
104
|
+
|
|
105
|
+
For more advanced topics, see the [Advanced Usage](https://httpx2.pydantic.dev/advanced/) section, the [async support](https://httpx2.pydantic.dev/async/) section, or the [HTTP/2](https://httpx2.pydantic.dev/http2/) section.
|
|
106
|
+
|
|
107
|
+
The [Developer Interface](https://httpx2.pydantic.dev/api/) provides a comprehensive API reference.
|
|
108
|
+
|
|
109
|
+
To find out about tools that integrate with HTTPX, see [Third Party Packages](https://httpx2.pydantic.dev/third_party_packages/).
|
|
110
|
+
|
|
111
|
+
## Contribute
|
|
112
|
+
|
|
113
|
+
If you want to contribute with HTTPX2 check out the [Contributing Guide](https://httpx2.pydantic.dev/contributing/) to learn how to start.
|
|
114
|
+
|
|
115
|
+
## Dependencies
|
|
116
|
+
|
|
117
|
+
The HTTPX2 project relies on these excellent libraries:
|
|
118
|
+
|
|
119
|
+
* `httpcore2` - The underlying transport implementation for `httpx2`.
|
|
120
|
+
* `h11` - HTTP/1.1 support.
|
|
121
|
+
* `anyio` - Structured concurrency primitives, used to support both `asyncio` and `trio`.
|
|
122
|
+
* `certifi` - SSL certificates.
|
|
123
|
+
* `idna` - Internationalized domain name support.
|
|
124
|
+
|
|
125
|
+
As well as these optional installs:
|
|
126
|
+
|
|
127
|
+
* `h2` - HTTP/2 support. *(Optional, with `httpx2[http2]`)*
|
|
128
|
+
* `socksio` - SOCKS proxy support. *(Optional, with `httpx2[socks]`)*
|
|
129
|
+
* `rich` - Rich terminal support. *(Optional, with `httpx2[cli]`)*
|
|
130
|
+
* `click` - Command line client support. *(Optional, with `httpx2[cli]`)*
|
|
131
|
+
* `brotli` or `brotlicffi` - Decoding for "brotli" compressed responses. *(Optional, with `httpx2[brotli]`)*
|
|
132
|
+
* `zstandard` - Decoding for "zstd" compressed responses on Python 3.13 and below. *(Optional, with `httpx2[zstd]`. On Python 3.14+, `zstd` is supported natively via the stdlib [`compression.zstd`](https://docs.python.org/3/library/compression.zstd.html) module.)*
|
|
133
|
+
|
|
134
|
+
A huge amount of credit is due to `requests` for the API layout that
|
|
135
|
+
much of this work follows, as well as to `urllib3` for plenty of design
|
|
136
|
+
inspiration around the lower-level networking details.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
<p align="center"><i>HTTPX2 is <a href="https://github.com/pydantic/httpx2/blob/main/LICENSE.md">BSD licensed</a> code.<br/>Designed & crafted with care.</i><br/>— 🦋 —</p>
|
|
@@ -11,21 +11,6 @@ from ._transports import *
|
|
|
11
11
|
from ._types import *
|
|
12
12
|
from ._urls import *
|
|
13
13
|
|
|
14
|
-
try:
|
|
15
|
-
from ._main import main
|
|
16
|
-
except ImportError: # pragma: no cover
|
|
17
|
-
|
|
18
|
-
def main() -> None: # type: ignore
|
|
19
|
-
import sys
|
|
20
|
-
|
|
21
|
-
print(
|
|
22
|
-
"The httpx command line client could not run because the required "
|
|
23
|
-
"dependencies were not installed.\nMake sure you've installed "
|
|
24
|
-
"everything with: pip install 'httpx[cli]'"
|
|
25
|
-
)
|
|
26
|
-
sys.exit(1)
|
|
27
|
-
|
|
28
|
-
|
|
29
14
|
__all__ = [
|
|
30
15
|
"__description__",
|
|
31
16
|
"__title__",
|
|
@@ -60,7 +45,6 @@ __all__ = [
|
|
|
60
45
|
"InvalidURL",
|
|
61
46
|
"Limits",
|
|
62
47
|
"LocalProtocolError",
|
|
63
|
-
"main",
|
|
64
48
|
"MockTransport",
|
|
65
49
|
"NetRCAuth",
|
|
66
50
|
"NetworkError",
|
|
@@ -104,3 +88,20 @@ __locals = locals()
|
|
|
104
88
|
for __name in __all__:
|
|
105
89
|
if not __name.startswith("__"):
|
|
106
90
|
setattr(__locals[__name], "__module__", "httpx2") # noqa
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def __getattr__(name: str) -> object: # pragma: no cover
|
|
94
|
+
if name == "main":
|
|
95
|
+
import warnings
|
|
96
|
+
|
|
97
|
+
warnings.warn(
|
|
98
|
+
"`httpx2.main` is deprecated and will be removed in a future release. "
|
|
99
|
+
"Use the `httpx2` CLI entry point instead.",
|
|
100
|
+
DeprecationWarning,
|
|
101
|
+
stacklevel=2,
|
|
102
|
+
)
|
|
103
|
+
from ._main import main
|
|
104
|
+
|
|
105
|
+
return main
|
|
106
|
+
|
|
107
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -59,9 +59,7 @@ class Auth:
|
|
|
59
59
|
"""
|
|
60
60
|
yield request
|
|
61
61
|
|
|
62
|
-
def sync_auth_flow(
|
|
63
|
-
self, request: Request
|
|
64
|
-
) -> typing.Generator[Request, Response, None]:
|
|
62
|
+
def sync_auth_flow(self, request: Request) -> typing.Generator[Request, Response, None]:
|
|
65
63
|
"""
|
|
66
64
|
Execute the authentication flow synchronously.
|
|
67
65
|
|
|
@@ -84,9 +82,7 @@ class Auth:
|
|
|
84
82
|
except StopIteration:
|
|
85
83
|
break
|
|
86
84
|
|
|
87
|
-
async def async_auth_flow(
|
|
88
|
-
self, request: Request
|
|
89
|
-
) -> typing.AsyncGenerator[Request, Response]:
|
|
85
|
+
async def async_auth_flow(self, request: Request) -> typing.AsyncGenerator[Request, Response]:
|
|
90
86
|
"""
|
|
91
87
|
Execute the authentication flow asynchronously.
|
|
92
88
|
|
|
@@ -161,9 +157,7 @@ class NetRCAuth(Auth):
|
|
|
161
157
|
yield request
|
|
162
158
|
else:
|
|
163
159
|
# Build a basic auth header with credentials from the netrc file.
|
|
164
|
-
request.headers["Authorization"] = self._build_auth_header(
|
|
165
|
-
username=auth_info[0], password=auth_info[2]
|
|
166
|
-
)
|
|
160
|
+
request.headers["Authorization"] = self._build_auth_header(username=auth_info[0], password=auth_info[2])
|
|
167
161
|
yield request
|
|
168
162
|
|
|
169
163
|
def _build_auth_header(self, username: str | bytes, password: str | bytes) -> str:
|
|
@@ -192,9 +186,7 @@ class DigestAuth(Auth):
|
|
|
192
186
|
|
|
193
187
|
def auth_flow(self, request: Request) -> typing.Generator[Request, Response, None]:
|
|
194
188
|
if self._last_challenge:
|
|
195
|
-
request.headers["Authorization"] = self._build_auth_header(
|
|
196
|
-
request, self._last_challenge
|
|
197
|
-
)
|
|
189
|
+
request.headers["Authorization"] = self._build_auth_header(request, self._last_challenge)
|
|
198
190
|
|
|
199
191
|
response = yield request
|
|
200
192
|
|
|
@@ -214,16 +206,12 @@ class DigestAuth(Auth):
|
|
|
214
206
|
self._last_challenge = self._parse_challenge(request, response, auth_header)
|
|
215
207
|
self._nonce_count = 1
|
|
216
208
|
|
|
217
|
-
request.headers["Authorization"] = self._build_auth_header(
|
|
218
|
-
request, self._last_challenge
|
|
219
|
-
)
|
|
209
|
+
request.headers["Authorization"] = self._build_auth_header(request, self._last_challenge)
|
|
220
210
|
if response.cookies:
|
|
221
211
|
Cookies(response.cookies).set_cookie_header(request=request)
|
|
222
212
|
yield request
|
|
223
213
|
|
|
224
|
-
def _parse_challenge(
|
|
225
|
-
self, request: Request, response: Response, auth_header: str
|
|
226
|
-
) -> _DigestAuthChallenge:
|
|
214
|
+
def _parse_challenge(self, request: Request, response: Response, auth_header: str) -> _DigestAuthChallenge:
|
|
227
215
|
"""
|
|
228
216
|
Returns a challenge from a Digest WWW-Authenticate header.
|
|
229
217
|
These take the form of:
|
|
@@ -245,16 +233,12 @@ class DigestAuth(Auth):
|
|
|
245
233
|
algorithm = header_dict.get("algorithm", "MD5")
|
|
246
234
|
opaque = header_dict["opaque"].encode() if "opaque" in header_dict else None
|
|
247
235
|
qop = header_dict["qop"].encode() if "qop" in header_dict else None
|
|
248
|
-
return _DigestAuthChallenge(
|
|
249
|
-
realm=realm, nonce=nonce, algorithm=algorithm, opaque=opaque, qop=qop
|
|
250
|
-
)
|
|
236
|
+
return _DigestAuthChallenge(realm=realm, nonce=nonce, algorithm=algorithm, opaque=opaque, qop=qop)
|
|
251
237
|
except KeyError as exc:
|
|
252
238
|
message = "Malformed Digest WWW-Authenticate header"
|
|
253
239
|
raise ProtocolError(message, request=request) from exc
|
|
254
240
|
|
|
255
|
-
def _build_auth_header(
|
|
256
|
-
self, request: Request, challenge: _DigestAuthChallenge
|
|
257
|
-
) -> str:
|
|
241
|
+
def _build_auth_header(self, request: Request, challenge: _DigestAuthChallenge) -> str:
|
|
258
242
|
hash_func = self._ALGORITHM_TO_HASH_FUNCTION[challenge.algorithm.upper()]
|
|
259
243
|
|
|
260
244
|
def digest(data: bytes) -> bytes:
|
|
@@ -317,11 +301,7 @@ class DigestAuth(Auth):
|
|
|
317
301
|
for i, (field, value) in enumerate(header_fields.items()):
|
|
318
302
|
if i > 0:
|
|
319
303
|
header_value += ", "
|
|
320
|
-
template =
|
|
321
|
-
QUOTED_TEMPLATE
|
|
322
|
-
if field not in NON_QUOTED_FIELDS
|
|
323
|
-
else NON_QUOTED_TEMPLATE
|
|
324
|
-
)
|
|
304
|
+
template = QUOTED_TEMPLATE if field not in NON_QUOTED_FIELDS else NON_QUOTED_TEMPLATE
|
|
325
305
|
header_value += template.format(field, to_str(value))
|
|
326
306
|
|
|
327
307
|
return header_value
|