Skip to content

Commit d4aca3f

Browse files
httpx / ahttpx switcher (#108)
1 parent b58bf1d commit d4aca3f

File tree

6 files changed

+378
-90
lines changed

6 files changed

+378
-90
lines changed

docs/connections.md

Lines changed: 121 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ The mechanics of sending HTTP requests is dealt with by the `ConnectionPool` and
44

55
We can introspect a `Client` instance to get some visibility onto the state of the connection pool.
66

7-
```python
7+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
8+
9+
```{ .python .httpx }
810
>>> with httpx.Client() as cli
911
>>> urls = [
1012
... "https://www.wikipedia.org/",
@@ -23,6 +25,25 @@ We can introspect a `Client` instance to get some visibility onto the state of t
2325
... # ]
2426
```
2527

28+
```{ .python .ahttpx .hidden }
29+
>>> async with ahttpx.Client() as cli
30+
>>> urls = [
31+
... "https://www.wikipedia.org/",
32+
... "https://www.theguardian.com/",
33+
... "https://news.ycombinator.com/",
34+
... ]
35+
... for url in urls:
36+
... await cli.get(url)
37+
... print(cli.transport)
38+
... # <ConnectionPool [3 idle]>
39+
... print(cli.transport.connections)
40+
... # [
41+
... # <Connection "https://www.wikipedia.org/" IDLE>,
42+
... # <Connection "https://www.theguardian.com/" IDLE>,
43+
... # <Connection "https://news.ycombinator.com/" IDLE>,
44+
... # ]
45+
```
46+
2647
---
2748

2849
## Understanding the stack
@@ -31,25 +52,46 @@ The `Client` class is responsible for handling redirects and cookies.
3152

3253
It also ensures that outgoing requests include a default set of headers such as `User-Agent` and `Accept-Encoding`.
3354

34-
```python
35-
with httpx.Client() as cli:
36-
r = cli.request("GET", "https://www.example.com/")
55+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
56+
57+
```{ .python .httpx }
58+
>>> with httpx.Client() as cli:
59+
>>> r = cli.request("GET", "https://www.example.com/")
60+
```
61+
62+
```{ .python .ahttpx .hidden }
63+
>>> async with ahttpx.Client() as cli:
64+
>>> r = await cli.request("GET", "https://www.example.com/")
3765
```
3866

3967
The `Client` class sends requests using a `ConnectionPool`, which is responsible for managing a pool of HTTP connections. This ensures quicker and more efficient use of resources than opening and closing a TCP connection with each request. The connection pool also handles HTTP proxying if required.
4068

4169
A single connection pool is able to handle multiple concurrent requests, with locking in place to ensure that the pool does not become over-saturated.
4270

43-
```python
44-
with httpx.ConnectionPool() as pool:
45-
r = pool.request("GET", "https://www.example.com/")
71+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
72+
73+
```{ .python .httpx }
74+
>>> with httpx.ConnectionPool() as pool:
75+
>>> r = pool.request("GET", "https://www.example.com/")
76+
```
77+
78+
```{ .python .ahttpx .hidden }
79+
>>> async with ahttpx.ConnectionPool() as pool:
80+
>>> r = await pool.request("GET", "https://www.example.com/")
4681
```
4782

4883
Individual HTTP connections can be managed directly with the `Connection` class. A single connection can only handle requests sequentially. Locking is provided to ensure that requests are strictly queued sequentially.
4984

50-
```python
51-
with httpx.open_connection("https://www.example.com/") as conn:
52-
r = conn.request("GET", "/")
85+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
86+
87+
```{ .python .httpx }
88+
>>> with httpx.open_connection("https://www.example.com/") as conn:
89+
>>> r = conn.request("GET", "/")
90+
```
91+
92+
```{ .python .ahttpx .hidden }
93+
>>> async with ahttpx.open_connection("https://www.example.com/") as conn:
94+
>>> r = await conn.request("GET", "/")
5395
```
5496

5597
Protocol handling is dealt with using [the `h11` package](https://h11.readthedocs.io/en/latest/), a rigorously designed HTTP/1.1 implementation which follows [the Sans-IO design pattern](https://sans-io.readthedocs.io/).
@@ -60,33 +102,61 @@ The `NetworkBackend` is responsible for managing the TCP stream, providing a raw
60102

61103
## ConnectionPool
62104

63-
```python
105+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
106+
107+
```{ .python .httpx }
64108
>>> pool = httpx.ConnectionPool()
65109
>>> pool
66110
<ConnectionPool [0 active]>
67111
```
68112

113+
```{ .python .ahttpx .hidden }
114+
>>> pool = ahttpx.ConnectionPool()
115+
>>> pool
116+
<ConnectionPool [0 active]>
117+
```
118+
69119
### `.request(method, url, headers=None, content=None)`
70120

71-
```python
121+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
122+
123+
```{ .python .httpx }
72124
>>> with httpx.ConnectionPool() as pool:
73125
>>> res = pool.request("GET", "https://www.example.com")
74126
>>> res, pool
75127
<Response [200 OK]>, <ConnectionPool [1 idle]>
76128
```
77129

130+
```{ .python .ahttpx .hidden }
131+
>>> async with ahttpx.ConnectionPool() as pool:
132+
>>> res = await pool.request("GET", "https://www.example.com")
133+
>>> res, pool
134+
<Response [200 OK]>, <ConnectionPool [1 idle]>
135+
```
136+
78137
### `.stream(method, url, headers=None, content=None)`
79138

80-
```python
139+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
140+
141+
```{ .python .httpx }
81142
>>> with httpx.ConnectionPool() as pool:
82143
>>> with pool.stream("GET", "https://www.example.com") as res:
83144
>>> res, pool
84145
<Response [200 OK]>, <ConnectionPool [1 active]>
85146
```
86147

148+
```{ .python .ahttpx .hidden }
149+
>>> with ahttpx.ConnectionPool() as pool:
150+
>>> with await pool.stream("GET", "https://www.example.com") as res:
151+
>>> res, pool
152+
<Response [200 OK]>, <ConnectionPool [1 active]>
153+
```
154+
87155
### `.send(request)`
88156

89-
```python
157+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
158+
159+
```{ .python .httpx }
90160
>>> with httpx.ConnectionPool() as pool:
91161
>>> req = httpx.Request("GET", "https://www.example.com")
92162
>>> with pool.send(req) as res:
@@ -95,14 +165,31 @@ The `NetworkBackend` is responsible for managing the TCP stream, providing a raw
95165
<Response [200 OK]>, <ConnectionPool [1 idle]>
96166
```
97167

168+
```{ .python .ahttpx .hidden }
169+
>>> with ahttpx.ConnectionPool() as pool:
170+
>>> req = ahttpx.Request("GET", "https://www.example.com")
171+
>>> async with await pool.send(req) as res:
172+
>>> await res.read()
173+
>>> res, pool
174+
<Response [200 OK]>, <ConnectionPool [1 idle]>
175+
```
176+
98177
### `.close()`
99178

100-
```python
179+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
180+
181+
```{ .python .httpx }
101182
>>> with httpx.ConnectionPool() as pool:
102183
>>> pool.close()
103184
<ConnectionPool [0 active]>
104185
```
105186

187+
```{ .python .ahttpx .hidden }
188+
>>> with ahttpx.ConnectionPool() as pool:
189+
>>> await pool.close()
190+
<ConnectionPool [0 active]>
191+
```
192+
106193
---
107194

108195
## Connection
@@ -113,23 +200,40 @@ The `NetworkBackend` is responsible for managing the TCP stream, providing a raw
113200

114201
## Protocol upgrades
115202

116-
```python
203+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
204+
205+
```{ .python .httpx }
117206
with httpx.open_connection("https://www.example.com/") as conn:
118207
with conn.upgrade("GET", "/feed", {"Upgrade": "WebSocket"}) as stream:
119208
...
120209
```
121210

211+
```{ .python .ahttpx .hidden }
212+
async with await ahttpx.open_connection("https://www.example.com/") as conn:
213+
async with await conn.upgrade("GET", "/feed", {"Upgrade": "WebSocket"}) as stream:
214+
...
215+
```
216+
122217
`<Connection “https://www.example.com/feed” WEBSOCKET>`
123218

124219
## Proxy `CONNECT` requests
125220

126-
```python
221+
<div class="tabs"><a onclick="httpx()" class="httpx">httpx</a> <a onclick="ahttpx()" class="ahttpx hidden">ahttpx</a></div>
222+
223+
```{ .python .httpx }
127224
with httpx.open_connection("http://127.0.0.1:8080") as conn:
128225
with conn.upgrade("CONNECT", "www.encode.io:443") as stream:
129226
stream.start_tls(ctx, hostname="www.encode.io")
130227
...
131228
```
132229

230+
```{ .python .ahttpx .hidden }
231+
async with await ahttpx.open_connection("http://127.0.0.1:8080") as conn:
232+
async with await conn.upgrade("CONNECT", "www.encode.io:443") as stream:
233+
await stream.start_tls(ctx, hostname="www.encode.io")
234+
...
235+
```
236+
133237
`<Connection "https://www.encode.io" VIA “http://127.0.0.1:8080” CONNECT>`
134238

135239
---

0 commit comments

Comments
 (0)