Requests & Responses¶
The Request object¶
Annotate a parameter as Request to receive the incoming request:
from veloce import Request, Veloce
app = Veloce()
@app.get("/inspect")
async def inspect(request: Request):
return {
"method": request.method,
"path": request.path,
"query": dict(request.query_params),
"user_agent": request.headers.get("user-agent"),
}
request.headers and request.query_params are multi-value mappings:
headers["x"] returns the first value, headers.getlist("x") returns
all of them.
Returning responses¶
A handler can return several shapes — Veloce coerces each to a response:
@app.get("/dict")
async def as_dict(request: Request):
return {"json": True} # -> JSON response
@app.get("/tuple")
async def as_tuple(request: Request):
return {"created": True}, 201 # -> JSON with an explicit status
For explicit control, return a response object:
from veloce import HTMLResponse, JSONResponse
@app.get("/html")
async def html(request: Request):
return HTMLResponse("<h1>Hello from Veloce</h1>")
@app.get("/json")
async def json(request: Request):
return JSONResponse({"ok": True}, status_code=200)
Other response classes include PlainTextResponse, RedirectResponse,
FileResponse, StreamingResponse, and ORJSONResponse /
UJSONResponse.
Request bodies with Pydantic¶
Annotate a parameter with a Pydantic model — Veloce parses and validates
the body before the handler runs. Invalid input produces a structured
422 automatically:
from pydantic import BaseModel
class UserCreate(BaseModel):
name: str
email: str
age: int = 0
@app.post("/users")
async def create_user(user: UserCreate):
return {"stored": user.model_dump()}
Shaping output with response_model¶
response_model runs the return value through a model on the way out —
useful for trimming internal fields:
class UserPublic(BaseModel):
id: int
name: str
@app.get("/users/{user_id}", response_model=UserPublic)
async def get_user(user_id: int):
# extra keys like "password_hash" are dropped from the response
return {"id": user_id, "name": "ada", "password_hash": "..."}
Errors¶
Raise HTTPException anywhere to stop with a status code and message:
from veloce import HTTPException
@app.get("/users/{user_id}")
async def get_user(user_id: int):
if user_id != 1:
raise HTTPException(404, f"User {user_id} not found")
return {"id": user_id}
Register a custom handler to control the error payload: