Skip to content

v3.10.0

Choose a tag to compare

@kennethreitz kennethreitz released this 12 Jun 02:49
· 6 commits to main since this release

Highlights

Trailing-slash redirects. /users/ now 307-redirects to /users (and vice versa) instead of 404ing, preserving the method and query string. The most common routing footgun, gone. Strict matchers can opt out:

api = responder.API(redirect_slashes=False)

Request size limits. Close the unbounded-upload DoS vector with one parameter — oversized bodies get 413, whether read via await req.content, req.media(), or streamed:

api = responder.API(max_request_size=10 * 1024 * 1024)  # 10 MB

Fail-fasts on Content-Length when present, enforces cumulatively for chunked uploads, and negotiates JSON error bodies for JSON clients.

Automatic ETags. API(auto_etag=True) gives every GET response a content-hash ETag with full 304 Not Modified handling — zero per-route code. An explicit resp.etag always wins.

After-response background tasks. Defer work until the client has the response:

@api.route("/signup", methods=["POST"])
async def signup(req, resp):
    resp.media = {"ok": True}
    resp.background(send_welcome_email, "user@example.com")

Cache-Control helper. resp.cache_control(public=True, max_age=3600) — pairs with 3.9.1's conditional requests to round out the caching story.

Changed

  • Trailing-slash redirects are on by default (previously such requests were 404s).

Fixed

  • A 413 raised while reading the body during request_model validation is no longer swallowed into a 422.

Full changelog: https://github.com/kennethreitz/responder/blob/main/CHANGELOG.md

PyPI: https://pypi.org/project/responder/3.10.0/