v3.12.0
Highlights
Built-in Prometheus metrics. One parameter, zero dependencies:
api = responder.API(metrics_route="/metrics")Request counters (responder_requests_total{method,path,status}) and latency histograms (responder_request_duration_seconds) in Prometheus text format. Labels use route patterns (/users/{id}) so cardinality stays bounded, and errors are recorded with their real status codes.
Server-side sessions. Cookie-payload sessions cap out at ~4KB and can't be revoked. Move the data server-side — only an opaque ID travels in the cookie, and handler code is unchanged:
from responder.ext.sessions import MemorySessionBackend, RedisSessionBackend
api = responder.API(session_backend=RedisSessionBackend(url="redis://localhost"))Custom backends need just get/set/delete.
Query-parameter validation. params_model completes the Pydantic story:
class SearchParams(BaseModel):
q: str
limit: int = 10
@api.route("/search", params_model=SearchParams)
async def search(req, resp):
params = req.state.validated_params # coerced & validatedInvalid queries get a 422, repeated keys map to list fields, and the parameters appear in your OpenAPI spec automatically.
resp.render(). resp.render("hello.html", name=name) — one call to render a template as the HTML body.
Full changelog: https://github.com/kennethreitz/responder/blob/main/CHANGELOG.md