0
# HTTP Route Handlers
1
2
Decorators and classes for handling HTTP requests including GET, POST, PUT, DELETE, PATCH, and generic route handlers. Route handlers process incoming HTTP requests and generate responses.
3
4
## Capabilities
5
6
### HTTP Method Decorators
7
8
Decorators for creating route handlers for specific HTTP methods. Each decorator creates an HTTPRouteHandler instance configured for the specified HTTP method.
9
10
```python { .api }
11
def get(
12
path: str | Sequence[str] | None = None,
13
*,
14
after_request: AfterRequestHookHandler | None = None,
15
after_response: AfterResponseHookHandler | None = None,
16
background: BackgroundTask | BackgroundTasks | None = None,
17
before_request: BeforeRequestHookHandler | None = None,
18
cache: bool | int | CacheKeyBuilder = False,
19
dependencies: Dependencies | None = None,
20
dto: type[AbstractDTO] | None = None,
21
etag: ETagConfig | None = None,
22
exception_handlers: ExceptionHandlersMap | None = None,
23
guards: Sequence[Guard] | None = None,
24
http_method: HttpMethod | str = HttpMethod.GET,
25
media_type: MediaType | str | None = None,
26
middleware: Sequence[Middleware] | None = None,
27
name: str | None = None,
28
opt: dict[str, Any] | None = None,
29
return_dto: type[AbstractDTO] | None = None,
30
signature_namespace: dict[str, Any] | None = None,
31
status_code: int | None = None,
32
summary: str | None = None,
33
description: str | None = None,
34
tags: Sequence[str] | None = None,
35
type_encoders: TypeEncodersMap | None = None,
36
include_in_schema: bool = True,
37
sync_to_thread: bool = True,
38
content_encoding: str | None = None,
39
content_media_type: str | None = None,
40
) -> Callable[[AnyCallable], HTTPRouteHandler]:
41
"""
42
Create a route handler for GET requests.
43
44
Parameters:
45
- path: Route path(s) - can be a string or sequence of strings
46
- after_request: Hook called after request processing
47
- after_response: Hook called after response sending
48
- background: Background task(s) to execute after response
49
- before_request: Hook called before request processing
50
- cache: Response caching configuration
51
- dependencies: Route-specific dependency providers
52
- dto: DTO for request body serialization
53
- etag: ETag configuration for caching
54
- exception_handlers: Route-specific exception handlers
55
- guards: Authorization guards
56
- http_method: HTTP method (defaults to GET)
57
- media_type: Response media type
58
- middleware: Route-specific middleware
59
- name: Route name for URL generation
60
- opt: Arbitrary options dictionary
61
- return_dto: DTO for response serialization
62
- signature_namespace: Additional namespace for signature inspection
63
- status_code: Default response status code
64
- summary: OpenAPI summary
65
- description: OpenAPI description
66
- tags: OpenAPI tags
67
- type_encoders: Route-specific type encoders
68
- include_in_schema: Include in OpenAPI schema
69
- sync_to_thread: Run sync handlers in thread pool
70
- content_encoding: Response content encoding
71
- content_media_type: Response content media type
72
73
Returns:
74
Decorator function that creates an HTTPRouteHandler
75
"""
76
77
def post(
78
path: str | Sequence[str] | None = None,
79
**kwargs: Any
80
) -> Callable[[AnyCallable], HTTPRouteHandler]:
81
"""Create a route handler for POST requests."""
82
83
def put(
84
path: str | Sequence[str] | None = None,
85
**kwargs: Any
86
) -> Callable[[AnyCallable], HTTPRouteHandler]:
87
"""Create a route handler for PUT requests."""
88
89
def patch(
90
path: str | Sequence[str] | None = None,
91
**kwargs: Any
92
) -> Callable[[AnyCallable], HTTPRouteHandler]:
93
"""Create a route handler for PATCH requests."""
94
95
def delete(
96
path: str | Sequence[str] | None = None,
97
**kwargs: Any
98
) -> Callable[[AnyCallable], HTTPRouteHandler]:
99
"""Create a route handler for DELETE requests."""
100
101
def head(
102
path: str | Sequence[str] | None = None,
103
**kwargs: Any
104
) -> Callable[[AnyCallable], HTTPRouteHandler]:
105
"""Create a route handler for HEAD requests."""
106
107
def route(
108
path: str | Sequence[str] | None = None,
109
*,
110
http_method: HttpMethod | str | Sequence[HttpMethod | str],
111
**kwargs: Any
112
) -> Callable[[AnyCallable], HTTPRouteHandler]:
113
"""Create a route handler for multiple HTTP methods."""
114
```
115
116
### HTTPRouteHandler Class
117
118
The underlying route handler class created by HTTP method decorators. Can be instantiated directly for advanced configuration.
119
120
```python { .api }
121
class HTTPRouteHandler(BaseRouteHandler):
122
def __init__(
123
self,
124
fn: AnyCallable,
125
*,
126
http_method: HttpMethod | str | Sequence[HttpMethod | str],
127
path: str | Sequence[str] | None = None,
128
status_code: int | None = None,
129
media_type: MediaType | str | None = None,
130
# ... same parameters as decorators
131
):
132
"""
133
Create an HTTP route handler.
134
135
Parameters:
136
- fn: Handler function
137
- http_method: HTTP method(s) to handle
138
- path: Route path(s)
139
- status_code: Default response status code
140
- media_type: Response media type
141
"""
142
143
@property
144
def http_methods(self) -> set[Method]:
145
"""Get HTTP methods handled by this route."""
146
147
async def handle_request(self, request: Request) -> Response:
148
"""Process incoming request and generate response."""
149
```
150
151
### ASGI Route Handler
152
153
Route handler for integrating existing ASGI applications or middleware.
154
155
```python { .api }
156
def asgi(
157
path: str | Sequence[str] | None = None,
158
*,
159
is_mount: bool = False,
160
**kwargs: Any
161
) -> Callable[[Callable[[Scope, Receive, Send], Awaitable[None]]], ASGIRouteHandler]:
162
"""
163
Create an ASGI route handler.
164
165
Parameters:
166
- path: Route path(s)
167
- is_mount: Whether to mount the ASGI app at the path
168
"""
169
170
class ASGIRouteHandler(BaseRouteHandler):
171
def __init__(
172
self,
173
fn: Callable[[Scope, Receive, Send], Awaitable[None]],
174
*,
175
is_mount: bool = False,
176
**kwargs: Any
177
):
178
"""Create an ASGI route handler."""
179
```
180
181
### Path Parameters
182
183
Path parameter parsing with type conversion and validation.
184
185
```python { .api }
186
# Path parameter types in route paths:
187
# {param_name:int} - Integer parameter
188
# {param_name:float} - Float parameter
189
# {param_name:str} - String parameter (default)
190
# {param_name:uuid} - UUID parameter
191
# {param_name:path} - Path parameter (preserves slashes)
192
```
193
194
## Usage Examples
195
196
### Basic Route Handlers
197
198
```python
199
from litestar import get, post, put, delete
200
from litestar.dto import DataclassDTO
201
from dataclasses import dataclass
202
203
@dataclass
204
class User:
205
name: str
206
email: str
207
id: int | None = None
208
209
@get("/users")
210
async def list_users() -> list[User]:
211
return [User(id=1, name="Alice", email="alice@example.com")]
212
213
@get("/users/{user_id:int}")
214
async def get_user(user_id: int) -> User:
215
return User(id=user_id, name="Alice", email="alice@example.com")
216
217
@post("/users", dto=DataclassDTO[User])
218
async def create_user(data: User) -> User:
219
# Simulate user creation
220
data.id = 123
221
return data
222
223
@put("/users/{user_id:int}", dto=DataclassDTO[User])
224
async def update_user(user_id: int, data: User) -> User:
225
data.id = user_id
226
return data
227
228
@delete("/users/{user_id:int}")
229
async def delete_user(user_id: int) -> dict[str, str]:
230
return {"status": "deleted", "user_id": str(user_id)}
231
```
232
233
### Path Parameters and Query Parameters
234
235
```python
236
from litestar import get
237
from litestar.params import Parameter
238
239
@get("/users/{user_id:int}/posts/{post_id:uuid}")
240
async def get_user_post(
241
user_id: int,
242
post_id: UUID,
243
include_comments: bool = False,
244
limit: int = Parameter(default=10, ge=1, le=100)
245
) -> dict:
246
return {
247
"user_id": user_id,
248
"post_id": str(post_id),
249
"include_comments": include_comments,
250
"limit": limit
251
}
252
```
253
254
### Request Body Handling
255
256
```python
257
from litestar import post
258
from litestar.dto import DataclassDTO
259
from dataclasses import dataclass
260
from typing import Optional
261
262
@dataclass
263
class CreateUserRequest:
264
name: str
265
email: str
266
age: Optional[int] = None
267
268
@post("/users", dto=DataclassDTO[CreateUserRequest])
269
async def create_user_with_validation(data: CreateUserRequest) -> dict:
270
# data is automatically validated and converted
271
return {"message": f"Created user {data.name} with email {data.email}"}
272
273
# For raw request body access
274
@post("/upload")
275
async def upload_file(request: Request) -> dict:
276
body = await request.body()
277
return {"size": len(body)}
278
```
279
280
### Multiple HTTP Methods
281
282
```python
283
from litestar import route, HttpMethod
284
285
@route("/api/resource", http_method=[HttpMethod.GET, HttpMethod.POST])
286
async def handle_resource(request: Request) -> dict:
287
if request.method == "GET":
288
return {"action": "fetch"}
289
elif request.method == "POST":
290
data = await request.json()
291
return {"action": "create", "data": data}
292
```
293
294
### Response Configuration
295
296
```python
297
from litestar import get, post
298
from litestar.response import Response
299
from litestar.status_codes import HTTP_201_CREATED, HTTP_202_ACCEPTED
300
301
@get("/health", status_code=200, media_type="text/plain")
302
async def health_check() -> str:
303
return "OK"
304
305
@post("/async-task", status_code=HTTP_202_ACCEPTED)
306
async def start_async_task(data: dict) -> dict:
307
# Start background processing
308
return {"task_id": "12345", "status": "accepted"}
309
310
@post("/users", status_code=HTTP_201_CREATED)
311
async def create_user_with_status(data: dict) -> dict:
312
# User creation logic
313
return {"id": 123, "status": "created"}
314
```
315
316
### Custom Response Types
317
318
```python
319
from litestar import get
320
from litestar.response import File, Stream, Redirect, Template
321
322
@get("/download/{filename:str}")
323
async def download_file(filename: str) -> File:
324
return File(f"/uploads/{filename}")
325
326
@get("/stream")
327
async def stream_data() -> Stream:
328
async def generate():
329
for i in range(100):
330
yield f"data chunk {i}\n"
331
332
return Stream(generate())
333
334
@get("/redirect")
335
async def redirect_example() -> Redirect:
336
return Redirect("/new-location")
337
338
@get("/page")
339
async def render_page() -> Template:
340
return Template("page.html", context={"title": "My Page"})
341
```
342
343
### Error Handling in Routes
344
345
```python
346
from litestar import get
347
from litestar.exceptions import HTTPException, NotFoundException
348
from litestar.status_codes import HTTP_400_BAD_REQUEST
349
350
@get("/users/{user_id:int}")
351
async def get_user_safe(user_id: int) -> dict:
352
if user_id < 1:
353
raise HTTPException(
354
detail="User ID must be positive",
355
status_code=HTTP_400_BAD_REQUEST
356
)
357
358
# Simulate user lookup
359
if user_id == 999:
360
raise NotFoundException("User not found")
361
362
return {"id": user_id, "name": "Alice"}
363
```
364
365
### Background Tasks
366
367
```python
368
from litestar import post
369
from litestar.background_tasks import BackgroundTask
370
371
def send_email(email: str, message: str) -> None:
372
# Email sending logic
373
print(f"Sending email to {email}: {message}")
374
375
@post("/notify", background=BackgroundTask(send_email, "admin@example.com", "New user registered"))
376
async def notify_admin(user_data: dict) -> dict:
377
return {"status": "success", "message": "Notification queued"}
378
```
379
380
## Types
381
382
```python { .api }
383
# Route handler function types
384
AnyCallable = Callable[..., Any]
385
RouteHandlerFunction = Callable[..., Any | Awaitable[Any]]
386
387
# HTTP method types
388
Method = Literal["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "TRACE"]
389
390
# Hook handler types
391
AfterRequestHookHandler = Callable[[Request], None | Awaitable[None]]
392
AfterResponseHookHandler = Callable[[Request, Response], None | Awaitable[None]]
393
BeforeRequestHookHandler = Callable[[Request], None | Awaitable[None]]
394
395
# Guard type
396
Guard = Callable[[ASGIConnection, BaseRouteHandler], bool | Awaitable[bool]]
397
398
# Cache types
399
CacheKeyBuilder = Callable[[Request], str]
400
401
# Type encoders
402
TypeEncodersMap = dict[Any, Callable[[Any], Any]]
403
```