0
# ASGI Middleware
1
2
Core middleware functionality for intercepting HTTP and WebSocket requests, extracting or generating correlation IDs, and making them available throughout the request lifecycle via context variables.
3
4
## Capabilities
5
6
### CorrelationIdMiddleware
7
8
ASGI middleware that processes incoming requests to extract correlation IDs from headers or generate new ones, then makes them available via context variables for the duration of the request.
9
10
```python { .api }
11
@dataclass
12
class CorrelationIdMiddleware:
13
"""
14
ASGI middleware for correlation ID management.
15
16
Parameters:
17
- app: The ASGI application to wrap
18
- header_name: Header name to look for correlation ID (default: 'X-Request-ID')
19
- update_request_header: Whether to update request headers with correlation ID
20
- generator: Function to generate new correlation IDs (default: uuid4().hex)
21
- validator: Function to validate existing correlation IDs (default: is_valid_uuid4)
22
- transformer: Function to transform correlation IDs (default: identity function)
23
"""
24
app: ASGIApp
25
header_name: str = 'X-Request-ID'
26
update_request_header: bool = True
27
generator: Callable[[], str] = field(default=lambda: uuid4().hex)
28
validator: Optional[Callable[[str], bool]] = field(default=is_valid_uuid4)
29
transformer: Optional[Callable[[str], str]] = field(default=lambda a: a)
30
31
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
32
"""
33
Process ASGI request with correlation ID handling.
34
35
For HTTP and WebSocket connections:
36
1. Extracts correlation ID from request headers
37
2. Validates ID using configured validator
38
3. Generates new ID if none found or validation fails
39
4. Transforms ID using configured transformer
40
5. Sets correlation ID in context variable
41
6. Updates response headers with correlation ID
42
7. Integrates with Sentry and Celery extensions if available
43
"""
44
```
45
46
The middleware automatically handles the complete correlation ID lifecycle:
47
48
1. **Header Detection**: Checks for correlation ID in incoming request headers
49
2. **Validation**: Validates existing IDs using the configured validator function
50
3. **Generation**: Creates new IDs when none exist or validation fails
51
4. **Transformation**: Applies any configured transformations to the ID
52
5. **Context Storage**: Makes the ID available via the `correlation_id` context variable
53
6. **Response Headers**: Includes the correlation ID in outgoing response headers
54
7. **Extension Integration**: Automatically integrates with Sentry and Celery when available
55
56
### UUID Validation
57
58
Utility function for validating UUID version 4 strings, used as the default validator in the middleware.
59
60
```python { .api }
61
def is_valid_uuid4(uuid_: str) -> bool:
62
"""
63
Check whether a string is a valid v4 uuid.
64
65
Parameters:
66
- uuid_: String to validate as UUID v4
67
68
Returns:
69
- bool: True if string is valid UUID v4, False otherwise
70
71
Raises:
72
- No exceptions (catches ValueError internally)
73
"""
74
```
75
76
## Usage Examples
77
78
### Basic Middleware Setup
79
80
```python
81
from fastapi import FastAPI
82
from asgi_correlation_id import CorrelationIdMiddleware
83
84
app = FastAPI()
85
app.add_middleware(CorrelationIdMiddleware)
86
```
87
88
### Custom Configuration
89
90
```python
91
from asgi_correlation_id import CorrelationIdMiddleware
92
import uuid
93
94
def custom_generator():
95
return f"req-{uuid.uuid4().hex[:8]}"
96
97
def custom_validator(id_value):
98
return id_value.startswith("req-") and len(id_value) == 12
99
100
app.add_middleware(
101
CorrelationIdMiddleware,
102
header_name='X-Correlation-ID',
103
update_request_header=True,
104
generator=custom_generator,
105
validator=custom_validator,
106
transformer=lambda x: x.upper()
107
)
108
```
109
110
### Starlette Integration
111
112
```python
113
from starlette.applications import Starlette
114
from starlette.middleware import Middleware
115
from asgi_correlation_id import CorrelationIdMiddleware
116
117
middleware = [
118
Middleware(CorrelationIdMiddleware, header_name='X-Request-ID')
119
]
120
121
app = Starlette(middleware=middleware)
122
```
123
124
## Types
125
126
```python { .api }
127
from typing import TYPE_CHECKING, Callable, Optional
128
from dataclasses import dataclass, field
129
130
if TYPE_CHECKING:
131
from starlette.types import ASGIApp, Message, Receive, Scope, Send
132
```