0
# Data Models
1
2
URL handling, headers management, query parameters, cookies, and other data structures used throughout the HTTP client. These models provide powerful and flexible ways to work with HTTP data while maintaining type safety and providing convenient access patterns.
3
4
## Capabilities
5
6
### URL Handling
7
8
Comprehensive URL parsing, manipulation, and validation with support for international domains and relative URLs.
9
10
```python { .api }
11
class URL:
12
def __init__(self, url, allow_relative=False, params=None):
13
"""
14
Create a URL object with parsing and validation.
15
16
Parameters:
17
- url (URLTypes): URL string or URL object
18
- allow_relative (bool): Whether to allow relative URLs (default: False)
19
- params (QueryParamTypes, optional): Query parameters to append
20
21
Raises:
22
InvalidURL: If URL is malformed or missing required components
23
"""
24
25
@property
26
def scheme(self) -> str:
27
"""URL scheme (http, https, etc.)."""
28
29
@property
30
def authority(self) -> str:
31
"""URL authority (host:port)."""
32
33
@property
34
def username(self) -> str:
35
"""Username from URL authority."""
36
37
@property
38
def password(self) -> str:
39
"""Password from URL authority."""
40
41
@property
42
def host(self) -> str:
43
"""Hostname."""
44
45
@property
46
def port(self) -> int:
47
"""Port number (defaults to 80 for http, 443 for https)."""
48
49
@property
50
def path(self) -> str:
51
"""URL path."""
52
53
@property
54
def query(self) -> str:
55
"""Query string."""
56
57
@property
58
def full_path(self) -> str:
59
"""Path with query string."""
60
61
@property
62
def fragment(self) -> str:
63
"""URL fragment."""
64
65
@property
66
def is_ssl(self) -> bool:
67
"""True if URL uses HTTPS."""
68
69
@property
70
def is_absolute_url(self) -> bool:
71
"""True if URL is absolute (has scheme and host)."""
72
73
@property
74
def is_relative_url(self) -> bool:
75
"""True if URL is relative."""
76
77
@property
78
def origin(self) -> "Origin":
79
"""Origin object for this URL."""
80
81
def copy_with(self, **kwargs) -> "URL":
82
"""
83
Create a copy with modified components.
84
85
Parameters:
86
- **kwargs: URL components to modify (scheme, host, path, etc.)
87
88
Returns:
89
URL: New URL with modifications
90
"""
91
92
def join(self, relative_url) -> "URL":
93
"""
94
Join with a relative URL.
95
96
Parameters:
97
- relative_url (URLTypes): Relative URL to join
98
99
Returns:
100
URL: New absolute URL
101
"""
102
```
103
104
**Usage Example:**
105
106
```python
107
import http3
108
109
# Basic URL creation
110
url = http3.URL('https://api.example.com/users?limit=10')
111
print(url.scheme) # 'https'
112
print(url.host) # 'api.example.com'
113
print(url.path) # '/users'
114
print(url.query) # 'limit=10'
115
116
# URL with parameters
117
url = http3.URL('https://api.example.com/search', params={'q': 'python', 'limit': 5})
118
print(url) # 'https://api.example.com/search?q=python&limit=5'
119
120
# URL manipulation
121
base_url = http3.URL('https://api.example.com')
122
full_url = base_url.join('/users/123')
123
print(full_url) # 'https://api.example.com/users/123'
124
125
# URL modification
126
modified = url.copy_with(path='/v2/search', port=8080)
127
print(modified) # 'https://api.example.com:8080/v2/search?q=python&limit=5'
128
```
129
130
### Origin Representation
131
132
Represents the origin (scheme + host + port) of a URL.
133
134
```python { .api }
135
class Origin:
136
def __init__(self, url):
137
"""Create an Origin from a URL."""
138
139
@property
140
def scheme(self) -> str:
141
"""Origin scheme."""
142
143
@property
144
def host(self) -> str:
145
"""Origin host."""
146
147
@property
148
def port(self) -> int:
149
"""Origin port."""
150
151
@property
152
def is_ssl(self) -> bool:
153
"""True if origin uses SSL/TLS."""
154
```
155
156
### Headers Management
157
158
Case-insensitive HTTP headers container with comprehensive manipulation methods.
159
160
```python { .api }
161
class Headers:
162
def __init__(self, headers=None):
163
"""
164
Create a headers container.
165
166
Parameters:
167
- headers (HeaderTypes, optional): Initial headers
168
"""
169
170
def __getitem__(self, key: str) -> str:
171
"""Get header value (case-insensitive)."""
172
173
def __setitem__(self, key: str, value: str):
174
"""Set header value (case-insensitive)."""
175
176
def __delitem__(self, key: str):
177
"""Delete header (case-insensitive)."""
178
179
def __contains__(self, key: str) -> bool:
180
"""Check if header exists (case-insensitive)."""
181
182
def __iter__(self):
183
"""Iterate over header names."""
184
185
def get(self, key: str, default=None):
186
"""
187
Get header value with default.
188
189
Parameters:
190
- key (str): Header name (case-insensitive)
191
- default: Default value if header not found
192
193
Returns:
194
Header value or default
195
"""
196
197
def get_list(self, key: str) -> List[str]:
198
"""
199
Get all values for a header as a list.
200
201
Parameters:
202
- key (str): Header name (case-insensitive)
203
204
Returns:
205
list: All values for the header
206
"""
207
208
def update(self, headers):
209
"""
210
Update headers with new values.
211
212
Parameters:
213
- headers (HeaderTypes): Headers to merge
214
"""
215
216
def keys(self):
217
"""Get all header names."""
218
219
def values(self):
220
"""Get all header values."""
221
222
def items(self):
223
"""Get (name, value) pairs."""
224
```
225
226
**Usage Example:**
227
228
```python
229
import http3
230
231
# Create headers
232
headers = http3.Headers({
233
'Content-Type': 'application/json',
234
'Authorization': 'Bearer token123'
235
})
236
237
# Case-insensitive access
238
print(headers['content-type']) # 'application/json'
239
print(headers['CONTENT-TYPE']) # 'application/json'
240
241
# Header manipulation
242
headers['User-Agent'] = 'MyApp/1.0'
243
del headers['authorization']
244
245
# Check for headers
246
if 'Content-Type' in headers:
247
content_type = headers.get('Content-Type', 'text/plain')
248
249
# Multiple values (e.g., Set-Cookie)
250
headers = http3.Headers([
251
('Set-Cookie', 'session=abc123'),
252
('Set-Cookie', 'user=john')
253
])
254
cookies = headers.get_list('Set-Cookie') # ['session=abc123', 'user=john']
255
```
256
257
### Query Parameters
258
259
Flexible query parameter handling with encoding and multiple value support.
260
261
```python { .api }
262
class QueryParams:
263
def __init__(self, params=None):
264
"""
265
Create a query parameters container.
266
267
Parameters:
268
- params (QueryParamTypes, optional): Initial parameters
269
"""
270
271
def __getitem__(self, key: str) -> str:
272
"""Get parameter value."""
273
274
def __setitem__(self, key: str, value: str):
275
"""Set parameter value."""
276
277
def __delitem__(self, key: str):
278
"""Delete parameter."""
279
280
def __contains__(self, key: str) -> bool:
281
"""Check if parameter exists."""
282
283
def __iter__(self):
284
"""Iterate over parameter names."""
285
286
def get(self, key: str, default=None):
287
"""
288
Get parameter value with default.
289
290
Parameters:
291
- key (str): Parameter name
292
- default: Default value if parameter not found
293
294
Returns:
295
Parameter value or default
296
"""
297
298
def get_list(self, key: str) -> List[str]:
299
"""
300
Get all values for a parameter as a list.
301
302
Parameters:
303
- key (str): Parameter name
304
305
Returns:
306
list: All values for the parameter
307
"""
308
309
def update(self, params):
310
"""
311
Update parameters with new values.
312
313
Parameters:
314
- params (QueryParamTypes): Parameters to merge
315
"""
316
317
def keys(self):
318
"""Get all parameter names."""
319
320
def values(self):
321
"""Get all parameter values."""
322
323
def items(self):
324
"""Get (name, value) pairs."""
325
```
326
327
**Usage Example:**
328
329
```python
330
import http3
331
332
# Create query parameters
333
params = http3.QueryParams({'q': 'python', 'limit': '10'})
334
335
# Alternative creation methods
336
params = http3.QueryParams([('q', 'python'), ('category', 'programming')])
337
params = http3.QueryParams('q=python&limit=10')
338
339
# Parameter access
340
search_term = params['q']
341
limit = params.get('limit', '20')
342
343
# Multiple values
344
params = http3.QueryParams([
345
('tag', 'python'),
346
('tag', 'web'),
347
('tag', 'api')
348
])
349
tags = params.get_list('tag') # ['python', 'web', 'api']
350
351
# Use with URL
352
url = http3.URL('https://api.example.com/search', params=params)
353
```
354
355
### Cookie Management
356
357
Comprehensive cookie handling with persistence and automatic management.
358
359
```python { .api }
360
class Cookies:
361
def __init__(self, cookies=None):
362
"""
363
Create a cookies container.
364
365
Parameters:
366
- cookies (CookieTypes, optional): Initial cookies
367
"""
368
369
def __getitem__(self, key: str) -> str:
370
"""Get cookie value."""
371
372
def __setitem__(self, key: str, value: str):
373
"""Set cookie value."""
374
375
def __delitem__(self, key: str):
376
"""Delete cookie."""
377
378
def __contains__(self, key: str) -> bool:
379
"""Check if cookie exists."""
380
381
def __iter__(self):
382
"""Iterate over cookie names."""
383
384
def get(self, name: str, default=None, domain=None, path=None):
385
"""
386
Get cookie value with optional domain/path filtering.
387
388
Parameters:
389
- name (str): Cookie name
390
- default: Default value if cookie not found
391
- domain (str, optional): Filter by domain
392
- path (str, optional): Filter by path
393
394
Returns:
395
Cookie value or default
396
"""
397
398
def set(self, name: str, value: str, domain=None, path=None):
399
"""
400
Set cookie with optional domain/path.
401
402
Parameters:
403
- name (str): Cookie name
404
- value (str): Cookie value
405
- domain (str, optional): Cookie domain
406
- path (str, optional): Cookie path
407
"""
408
409
def delete(self, name: str, domain=None, path=None):
410
"""
411
Delete cookie with optional domain/path filtering.
412
413
Parameters:
414
- name (str): Cookie name
415
- domain (str, optional): Filter by domain
416
- path (str, optional): Filter by path
417
"""
418
419
def clear(self, domain=None, path=None):
420
"""
421
Clear cookies with optional domain/path filtering.
422
423
Parameters:
424
- domain (str, optional): Filter by domain
425
- path (str, optional): Filter by path
426
"""
427
428
def update(self, cookies):
429
"""
430
Update cookies with new values.
431
432
Parameters:
433
- cookies (CookieTypes): Cookies to merge
434
"""
435
436
def keys(self):
437
"""Get all cookie names."""
438
439
def values(self):
440
"""Get all cookie values."""
441
442
def items(self):
443
"""Get (name, value) pairs."""
444
```
445
446
**Usage Example:**
447
448
```python
449
import http3
450
451
# Create cookies
452
cookies = http3.Cookies({'session': 'abc123', 'user': 'john'})
453
454
# Alternative creation
455
cookies = http3.Cookies([('session', 'abc123'), ('preferences', 'dark-mode')])
456
457
# Cookie access
458
session_id = cookies['session']
459
user = cookies.get('user', 'anonymous')
460
461
# Cookie manipulation
462
cookies['theme'] = 'dark'
463
del cookies['session']
464
465
# Domain-specific cookies
466
cookies.set('tracking', 'enabled', domain='.example.com')
467
tracking = cookies.get('tracking', domain='.example.com')
468
469
# Use with client
470
client = http3.Client(cookies=cookies)
471
```
472
473
### Type Aliases
474
475
Flexible type aliases for various data inputs:
476
477
```python { .api }
478
# URL types
479
URLTypes = Union[URL, str]
480
481
# Query parameter types
482
QueryParamTypes = Union[
483
QueryParams,
484
Mapping[str, str],
485
List[Tuple[Any, Any]],
486
str
487
]
488
489
# Header types
490
HeaderTypes = Union[
491
Headers,
492
Dict[AnyStr, AnyStr],
493
List[Tuple[AnyStr, AnyStr]]
494
]
495
496
# Cookie types
497
CookieTypes = Union[Cookies, CookieJar, Dict[str, str]]
498
499
# Authentication types
500
AuthTypes = Union[
501
Tuple[Union[str, bytes], Union[str, bytes]], # Basic auth
502
Callable[[AsyncRequest], AsyncRequest] # Custom auth
503
]
504
505
# Request data types
506
RequestData = Union[dict, str, bytes, Iterator[bytes]]
507
AsyncRequestData = Union[dict, str, bytes, AsyncIterator[bytes]]
508
509
# File upload types
510
RequestFiles = Dict[str, Union[
511
IO[AnyStr], # Simple file
512
Tuple[str, IO[AnyStr]], # (filename, file)
513
Tuple[str, IO[AnyStr], str] # (filename, file, content_type)
514
]]
515
516
# Response content types
517
ResponseContent = Union[bytes, Iterator[bytes]]
518
AsyncResponseContent = Union[bytes, AsyncIterator[bytes]]
519
```
520
521
## Advanced Usage
522
523
### URL Normalization and IDNA
524
525
```python
526
import http3
527
528
# International domain names
529
url = http3.URL('https://пример.рф/path')
530
print(url.host) # Automatically converted to ASCII
531
532
# URL normalization
533
url = http3.URL('HTTPS://Example.COM:443/Path/../Other')
534
print(url) # Normalized form
535
```
536
537
### Custom Header Handling
538
539
```python
540
import http3
541
542
# Custom headers for specific use cases
543
headers = http3.Headers()
544
headers['X-API-Key'] = 'secret-key'
545
headers['X-Request-ID'] = 'req-123'
546
547
# Handle multi-value headers
548
headers.update([
549
('Accept', 'application/json'),
550
('Accept', 'text/plain')
551
])
552
553
# Get all Accept values
554
accept_types = headers.get_list('Accept')
555
```
556
557
### Complex Query Parameters
558
559
```python
560
import http3
561
562
# Complex parameter structures
563
params = http3.QueryParams([
564
('filter[status]', 'active'),
565
('filter[type]', 'user'),
566
('sort', 'created_at'),
567
('include[]', 'profile'),
568
('include[]', 'permissions')
569
])
570
571
url = http3.URL('https://api.example.com/users', params=params)
572
# Results in: https://api.example.com/users?filter%5Bstatus%5D=active&...
573
```