mirror of
https://github.com/kennethreitz/responder.git
synced 2026-10-24 05:59:12 +00:00
3117 lines
298 KiB
HTML
3117 lines
298 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<html lang="en" data-content_root="./">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
|
||
<title>Changelog — responder 9.2.0 documentation</title>
|
||
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=5ecbeea2" />
|
||
<link rel="stylesheet" type="text/css" href="_static/basic.css?v=b08954a9" />
|
||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=eb4102c5" />
|
||
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
|
||
<link rel="stylesheet" type="text/css" href="_static/sphinx-design.min.css?v=95c83b7e" />
|
||
<link rel="stylesheet" type="text/css" href="_static/design-elements.e5416f61bae5d36adc6d722a2b6f8cff.css?v=452a8e97" />
|
||
<script src="_static/documentation_options.js?v=e8b940be"></script>
|
||
<script src="_static/doctools.js?v=fd6eb6e6"></script>
|
||
<script src="_static/sphinx_highlight.js?v=6ffebe34"></script>
|
||
<script src="_static/clipboard.min.js?v=a7894cd8"></script>
|
||
<script src="_static/copybutton.js?v=fd10adb8"></script>
|
||
<script>
|
||
</script>
|
||
<script src="_static/design-tabs.js?v=f930bc37"></script>
|
||
<script src="_static/design-elements.bbdccc18c4abea9397628f9fea3d48c2.js?v=03c7770e"></script>
|
||
<link rel="index" title="Index" href="genindex.html" />
|
||
<link rel="search" title="Search" href="search.html" />
|
||
<link rel="next" title="Migrating to v9" href="migration-v9.html" />
|
||
<link rel="prev" title="Runtime Contracts" href="runtime-contracts.html" />
|
||
|
||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||
|
||
|
||
|
||
|
||
|
||
</head><body>
|
||
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
|
||
|
||
<div class="body" role="main">
|
||
|
||
<section id="changelog">
|
||
<h1>Changelog<a class="headerlink" href="#changelog" title="Link to this heading">¶</a></h1>
|
||
<p>All notable changes to this project will be documented in this file.</p>
|
||
<p>The format is based on <a class="reference external" href="https://keepachangelog.com/en/1.0.0/">Keep a Changelog</a>, and
|
||
this project adheres to <a class="reference external" href="https://semver.org/spec/v2.0.0.html">Semantic Versioning</a>.</p>
|
||
<section id="unreleased">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v9.2.0..HEAD">Unreleased</a><a class="headerlink" href="#unreleased" title="Link to this heading">¶</a></h2>
|
||
<section id="changed">
|
||
<h3>Changed<a class="headerlink" href="#changed" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Installation documentation now recommends <code class="docutils literal notranslate"><span class="pre">responder[orjson]</span></code> on
|
||
standard GIL-enabled CPython, including combined feature extras and
|
||
deployment examples. Bare <code class="docutils literal notranslate"><span class="pre">responder</span></code> remains the compatibility install
|
||
for free-threaded interpreters and transparently uses the standard-library
|
||
JSON encoder when orjson is unavailable.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v9-2-0-2026-07-14">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v9.1.0..v9.2.0">v9.2.0</a> - 2026-07-14<a class="headerlink" href="#v9-2-0-2026-07-14" title="Link to this heading">¶</a></h2>
|
||
<p>Responder 9.2 makes typed SSE and NDJSON complete incremental response
|
||
contracts, from per-item runtime validation through OpenAPI and generated
|
||
streaming clients.</p>
|
||
<section id="added">
|
||
<h3>Added<a class="headerlink" href="#added" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Typed event streams: <code class="docutils literal notranslate"><span class="pre">@api.sse</span></code> and <code class="docutils literal notranslate"><span class="pre">@api.ndjson</span></code> infer item contracts
|
||
from sync or async iterator return annotations (or explicit
|
||
<code class="docutils literal notranslate"><span class="pre">event_model=</span></code> / <code class="docutils literal notranslate"><span class="pre">item_model=</span></code>), validate and serialize every yielded
|
||
item with Pydantic, and preserve backpressure and cancellation cleanup.
|
||
<code class="docutils literal notranslate"><span class="pre">responder.SSE[T]</span></code> adds typed <code class="docutils literal notranslate"><span class="pre">data</span></code> plus standard <code class="docutils literal notranslate"><span class="pre">event</span></code>, <code class="docutils literal notranslate"><span class="pre">id</span></code>, <code class="docutils literal notranslate"><span class="pre">retry</span></code>,
|
||
and comment metadata; SSE routes retain heartbeats and <code class="docutils literal notranslate"><span class="pre">Last-Event-ID</span></code>
|
||
support.</p></li>
|
||
<li><p>OpenAPI now documents typed streams with their wire media type and item
|
||
schema. Generated Python, JavaScript, TypeScript, Ruby, and PHP clients
|
||
consume them lazily as iterators, including typed SSE metadata events.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id1">
|
||
<h3>Changed<a class="headerlink" href="#id1" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>An immediately available first stream item is validated before response
|
||
headers, allowing contract failures to return <code class="docutils literal notranslate"><span class="pre">500</span></code>. Failures after a
|
||
stream begins are logged and terminate it without emitting the invalid
|
||
item. <code class="docutils literal notranslate"><span class="pre">HEAD</span></code> remains body-free and does not start the producer.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v9-1-0-2026-07-12">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v9.0.1..v9.1.0">v9.1.0</a> - 2026-07-12<a class="headerlink" href="#v9-1-0-2026-07-12" title="Link to this heading">¶</a></h2>
|
||
<p>Responder 9.1 makes Python return annotations complete HTTP response
|
||
contracts, from runtime validation through OpenAPI and generated clients.</p>
|
||
<section id="id2">
|
||
<h3>Added<a class="headerlink" href="#id2" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Return annotations are now complete response contracts. Any supported
|
||
Pydantic <code class="docutils literal notranslate"><span class="pre">TypeAdapter</span></code> shape — models, dataclasses, typed dictionaries,
|
||
collections such as <code class="docutils literal notranslate"><span class="pre">list[Item]</span></code>, unions, generic pagination models, and
|
||
JSON scalars — drives runtime validation and serialization, OpenAPI response
|
||
schemas, and generated-client types. Class-based-view method annotations and
|
||
Flask-style tuple annotations infer the same way. Inferred <code class="docutils literal notranslate"><span class="pre">str</span></code> and <code class="docutils literal notranslate"><span class="pre">bytes</span></code>
|
||
responses document and emit <code class="docutils literal notranslate"><span class="pre">text/plain</span></code> and <code class="docutils literal notranslate"><span class="pre">application/octet-stream</span></code>;
|
||
other inferred contracts use <code class="docutils literal notranslate"><span class="pre">application/json</span></code>.</p></li>
|
||
<li><p>Handlers may return <code class="docutils literal notranslate"><span class="pre">bool</span></code>, <code class="docutils literal notranslate"><span class="pre">int</span></code>, and <code class="docutils literal notranslate"><span class="pre">float</span></code> JSON scalars directly, in
|
||
addition to the existing dictionaries, lists, strings, bytes, models, and
|
||
dataclasses.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">responses={404:</span> <span class="pre">ErrorModel}</span></code> now declares a status-specific response
|
||
contract used for runtime validation and OpenAPI, including alternate
|
||
success statuses. A response mapping may provide <code class="docutils literal notranslate"><span class="pre">model</span></code> alongside a custom
|
||
description, headers, examples, or other OpenAPI metadata.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id3">
|
||
<h3>Changed<a class="headerlink" href="#id3" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Response contracts now validate the final success body after after-request
|
||
hooks. A body whose shape or response channel contradicts its declared model
|
||
fails closed with <code class="docutils literal notranslate"><span class="pre">500</span></code>, including a list returned for a single-object model;
|
||
<code class="docutils literal notranslate"><span class="pre">response_model=False</span></code> reliably disables inference and validation.</p></li>
|
||
<li><p>Flask-style return tuples now require exactly <code class="docutils literal notranslate"><span class="pre">(body,</span> <span class="pre">status)</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">(body,</span> <span class="pre">status,</span> <span class="pre">headers)</span></code>, a status integer from 100 through 599, and a
|
||
header mapping. Malformed tuples fail clearly instead of being partially
|
||
applied or silently ignored.</p></li>
|
||
<li><p>Routes with unresolved or unsupported return annotations now log a focused
|
||
registration warning with the <code class="docutils literal notranslate"><span class="pre">response_model=False</span></code> opt-out instead of
|
||
silently dropping the inferred contract.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="fixed">
|
||
<h3>Fixed<a class="headerlink" href="#fixed" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Informational, <code class="docutils literal notranslate"><span class="pre">204</span></code>, <code class="docutils literal notranslate"><span class="pre">205</span></code>, and <code class="docutils literal notranslate"><span class="pre">304</span></code> responses no longer send a body even
|
||
if a handler returned or assigned one. Their inferred OpenAPI success
|
||
responses omit content as well; <code class="docutils literal notranslate"><span class="pre">HEAD</span></code> continues to validate the
|
||
corresponding <code class="docutils literal notranslate"><span class="pre">GET</span></code> response while sending headers only.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v9-0-1-2026-07-06">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v9.0.0..v9.0.1">v9.0.1</a> - 2026-07-06<a class="headerlink" href="#v9-0-1-2026-07-06" title="Link to this heading">¶</a></h2>
|
||
<p>A bug-fix release from a post-9.0.0 adversarial scan: several v9-new
|
||
surfaces (CSRF, proxy headers, streaming form parsing, rate limiting,
|
||
GraphQL, OpenAPI caching) had crash or enforcement defects. Security-
|
||
relevant; upgrading from 9.0.0 is recommended.</p>
|
||
<section id="id4">
|
||
<h3>Fixed<a class="headerlink" href="#id4" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>CSRF: a non-ASCII submitted token (a fully client-controlled <code class="docutils literal notranslate"><span class="pre">csrf_token</span></code>
|
||
form field or <code class="docutils literal notranslate"><span class="pre">X-CSRF-Token</span></code> header) crashed <code class="docutils literal notranslate"><span class="pre">hmac.compare_digest</span></code> and
|
||
returned <code class="docutils literal notranslate"><span class="pre">500</span></code> instead of <code class="docutils literal notranslate"><span class="pre">403</span></code>; tokens are now compared as UTF-8 bytes.</p></li>
|
||
<li><p>CSRF: the per-route <code class="docutils literal notranslate"><span class="pre">csrf=</span></code> override was stored on the shared view object,
|
||
so re-registering a function with <code class="docutils literal notranslate"><span class="pre">csrf=False</span></code> stripped protection from its
|
||
earlier routes, and a CBV registered with <code class="docutils literal notranslate"><span class="pre">csrf=False</span></code> leaked the exemption
|
||
to subclasses through the MRO. Each registration’s value is now frozen onto
|
||
its own <code class="docutils literal notranslate"><span class="pre">Route</span></code>.</p></li>
|
||
<li><p>CSRF: <code class="docutils literal notranslate"><span class="pre">csrf=True</span></code> on a WebSocket route was accepted but never enforced; it
|
||
now raises at registration.</p></li>
|
||
<li><p>Proxy headers: a forwarded <code class="docutils literal notranslate"><span class="pre">Host</span></code> (or <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code>) whose port/value is
|
||
a non-ASCII digit character (e.g. <code class="docutils literal notranslate"><span class="pre">U+00B2</span></code>, which <code class="docutils literal notranslate"><span class="pre">str.isdigit()</span></code> accepts
|
||
but <code class="docutils literal notranslate"><span class="pre">int()</span></code> rejects) raised an unhandled <code class="docutils literal notranslate"><span class="pre">ValueError</span></code>. In
|
||
<code class="docutils literal notranslate"><span class="pre">ProxyHeadersMiddleware</span></code> — the outermost layer — this sent no response at
|
||
all; both call sites now require <code class="docutils literal notranslate"><span class="pre">.isascii()</span></code> before <code class="docutils literal notranslate"><span class="pre">int()</span></code>.</p></li>
|
||
<li><p>Rate limiting: <code class="docutils literal notranslate"><span class="pre">@limiter.limit</span></code> on a class-based-view method returned <code class="docutils literal notranslate"><span class="pre">500</span></code>
|
||
on every request because the wrapper mislocated the request/response past
|
||
the bound method’s <code class="docutils literal notranslate"><span class="pre">self</span></code>; they are now located by type.</p></li>
|
||
<li><p>GraphQL: a non-object JSON body (e.g. a JSON array) and a multipart POST
|
||
without a <code class="docutils literal notranslate"><span class="pre">query</span></code> field both returned <code class="docutils literal notranslate"><span class="pre">500</span></code>; both now return <code class="docutils literal notranslate"><span class="pre">400</span></code>.</p></li>
|
||
<li><p>Forms: a malformed or oversized multipart body on the buffered parse branch
|
||
raised an unhandled <code class="docutils literal notranslate"><span class="pre">500</span></code> instead of the documented <code class="docutils literal notranslate"><span class="pre">400</span></code>.</p></li>
|
||
<li><p>OpenAPI: the generated-document cache ignored <code class="docutils literal notranslate"><span class="pre">request_timeout</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">problem_details</span></code>, so changing either after the first render served a stale
|
||
schema; both are now part of the cache key.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v9-0-0-2026-07-05">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v8.3.0..v9.0.0">v9.0.0</a> - 2026-07-05<a class="headerlink" href="#v9-0-0-2026-07-05" title="Link to this heading">¶</a></h2>
|
||
<p>A major release: streaming multipart uploads, opt-in CSRF protection,
|
||
reverse-proxy header support, and the v8.1 deprecation path becoming the
|
||
default behavior. See the
|
||
<a class="reference external" href="https://responder.kennethreitz.org/migration-v9.html">v9 migration guide</a>
|
||
for the full upgrade path.</p>
|
||
<section id="id5">
|
||
<h3>Added<a class="headerlink" href="#id5" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Opt-in CSRF protection: <code class="docutils literal notranslate"><span class="pre">API(csrf=True)</span></code> requires unsafe requests
|
||
(<code class="docutils literal notranslate"><span class="pre">POST</span></code>/<code class="docutils literal notranslate"><span class="pre">PUT</span></code>/<code class="docutils literal notranslate"><span class="pre">PATCH</span></code>/<code class="docutils literal notranslate"><span class="pre">DELETE</span></code>) to present the session-bound token from
|
||
<code class="docutils literal notranslate"><span class="pre">req.csrf_token</span></code> in an <code class="docutils literal notranslate"><span class="pre">X-CSRF-Token</span></code> header or <code class="docutils literal notranslate"><span class="pre">csrf_token</span></code> form field
|
||
(<code class="docutils literal notranslate"><span class="pre">{{</span> <span class="pre">req.csrf_input</span> <span class="pre">}}</span></code> renders the hidden input for templates), rejecting
|
||
the rest with a <code class="docutils literal notranslate"><span class="pre">403</span></code>. Per-route overrides via
|
||
<code class="docutils literal notranslate"><span class="pre">@api.route(...,</span> <span class="pre">csrf=False)</span></code> (webhook receivers) or <code class="docutils literal notranslate"><span class="pre">csrf=True</span></code> (protect a
|
||
single route). The token check shares the request’s single streaming form
|
||
parse. Off by default; requires sessions.</p></li>
|
||
<li><p>Proxy-headers support: <code class="docutils literal notranslate"><span class="pre">API(trust_proxy_headers=True)</span></code> now installs a
|
||
middleware honoring RFC 7239 <code class="docutils literal notranslate"><span class="pre">Forwarded</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">X-Forwarded-Proto</span></code>/<code class="docutils literal notranslate"><span class="pre">X-Forwarded-Host</span></code>/<code class="docutils literal notranslate"><span class="pre">X-Forwarded-For</span></code>/<code class="docutils literal notranslate"><span class="pre">X-Real-IP</span></code>,
|
||
rewriting the request’s scheme, host, and client address to what the
|
||
original client sent — HTTPS detection, redirects, URL building,
|
||
trusted-host validation, and logged client IPs are then correct behind
|
||
nginx/Caddy/load balancers.</p></li>
|
||
<li><p>Streaming multipart uploads: multipart bodies now parse incrementally off
|
||
the wire, spooling file parts to temporary files (rolling to disk past
|
||
~1 MB) instead of buffering the whole body in RAM. <code class="docutils literal notranslate"><span class="pre">File()</span></code> markers,
|
||
<code class="docutils literal notranslate"><span class="pre">req.media("files")</span></code>, and <code class="docutils literal notranslate"><span class="pre">req.media("form")</span></code> all share the single
|
||
streaming parse, and <code class="docutils literal notranslate"><span class="pre">max_request_size</span></code> is enforced chunk-by-chunk as the
|
||
body arrives — uploads are bounded by disk, not memory.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id6">
|
||
<h3>Changed<a class="headerlink" href="#id6" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">trust_proxy_headers=True</span></code> previously only affected the client IP recorded
|
||
by <code class="docutils literal notranslate"><span class="pre">enable_logging</span></code>; it now rewrites the connection’s scheme, host, and
|
||
client address for the whole stack (see Added). Apps that enabled it purely
|
||
for logging get the same logged IPs, plus correct scheme/host handling.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">max_request_size</span></code> now defaults to 100 MiB instead of unlimited; pass
|
||
<code class="docutils literal notranslate"><span class="pre">API(max_request_size=None)</span></code> for the previous behavior. Oversized bodies
|
||
get a <code class="docutils literal notranslate"><span class="pre">413</span></code> as before.</p></li>
|
||
<li><p>Generated OpenAPI operations now document Responder’s operational responses:
|
||
CSRF-protected unsafe routes get <code class="docutils literal notranslate"><span class="pre">403</span></code>, rate-limited routes get <code class="docutils literal notranslate"><span class="pre">429</span></code> (and
|
||
fail-closed backend <code class="docutils literal notranslate"><span class="pre">503</span></code>), and request-size <code class="docutils literal notranslate"><span class="pre">413</span></code> is emitted only when a
|
||
body cap is active. Rate limiter <code class="docutils literal notranslate"><span class="pre">429</span></code>/<code class="docutils literal notranslate"><span class="pre">503</span></code> responses now honor
|
||
<code class="docutils literal notranslate"><span class="pre">API(problem_details=True)</span></code> and keep the legacy <code class="docutils literal notranslate"><span class="pre">{"error":</span> <span class="pre">...}</span></code> JSON shape
|
||
when <code class="docutils literal notranslate"><span class="pre">problem_details=False</span></code>.</p></li>
|
||
<li><p>Because multipart parsing streams, the raw body is consumed by the parse:
|
||
<code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">req.content</span></code> after <code class="docutils literal notranslate"><span class="pre">media("form"/"files")</span></code> raises a clear
|
||
<code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code> (await <code class="docutils literal notranslate"><span class="pre">req.content</span></code> first to keep the buffered, replayable
|
||
8.x behavior), and handlers using <code class="docutils literal notranslate"><span class="pre">File()</span></code>/<code class="docutils literal notranslate"><span class="pre">Form()</span></code> markers no longer have
|
||
the raw multipart body available (matching Starlette/FastAPI). Multipart
|
||
text fields read via <code class="docutils literal notranslate"><span class="pre">media("form")</span></code> now share the streaming parser’s
|
||
limits (1000 parts, 1 MB per text field, <code class="docutils literal notranslate"><span class="pre">400</span></code> beyond them) and lossily
|
||
decode invalid UTF-8 instead of silently dropping the field.</p></li>
|
||
<li><p>Prepared the v9 behavior defaults: explicit <code class="docutils literal notranslate"><span class="pre">port=</span></code> now wins over a
|
||
conflicting <code class="docutils literal notranslate"><span class="pre">PORT</span></code> environment variable, bare <code class="docutils literal notranslate"><span class="pre">add_route()</span></code> calls require an
|
||
explicit endpoint by default, <code class="docutils literal notranslate"><span class="pre">Decimal</span></code> values serialize as strings by
|
||
default, and GraphQL partial-data responses default to HTTP <code class="docutils literal notranslate"><span class="pre">200</span></code>. The
|
||
explicit compatibility switches for these legacy behaviors remain available
|
||
without deprecation warnings while apps migrate.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="removed">
|
||
<h3>Removed<a class="headerlink" href="#removed" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Removed the deprecated <code class="docutils literal notranslate"><span class="pre">API.session()</span></code> accessor. Use <code class="docutils literal notranslate"><span class="pre">api.requests</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">api.test_client(...)</span></code> instead.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v8-3-0-2026-07-05">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v8.2.3..v8.3.0">v8.3.0</a> - 2026-07-05<a class="headerlink" href="#v8-3-0-2026-07-05" title="Link to this heading">¶</a></h2>
|
||
<section id="id7">
|
||
<h3>Added<a class="headerlink" href="#id7" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Added <code class="docutils literal notranslate"><span class="pre">api.test_client(...)</span></code>, a configurable form of <code class="docutils literal notranslate"><span class="pre">api.requests</span></code> for
|
||
custom <code class="docutils literal notranslate"><span class="pre">base_url</span></code> values and Starlette <code class="docutils literal notranslate"><span class="pre">TestClient</span></code> options such as
|
||
<code class="docutils literal notranslate"><span class="pre">raise_server_exceptions=False</span></code>, without relying on deprecated
|
||
<code class="docutils literal notranslate"><span class="pre">api.session()</span></code>.</p></li>
|
||
<li><p>Added v9 compatibility opt-ins: <code class="docutils literal notranslate"><span class="pre">API(json_decimal="string")</span></code> serializes
|
||
<code class="docutils literal notranslate"><span class="pre">Decimal</span></code> values as precision-preserving strings, and
|
||
<code class="docutils literal notranslate"><span class="pre">api.graphql(...,</span> <span class="pre">partial_data_status=200)</span></code> returns GraphQL partial-data
|
||
responses with HTTP <code class="docutils literal notranslate"><span class="pre">200</span></code> per the GraphQL-over-HTTP spec. Apps can also pass
|
||
<code class="docutils literal notranslate"><span class="pre">API(implicit_static_fallback=False)</span></code> to disable bare <code class="docutils literal notranslate"><span class="pre">add_route()</span></code> static
|
||
fallbacks early, and <code class="docutils literal notranslate"><span class="pre">port_precedence="explicit"</span></code> to <code class="docutils literal notranslate"><span class="pre">serve()</span></code> / <code class="docutils literal notranslate"><span class="pre">run()</span></code> so
|
||
an explicit <code class="docutils literal notranslate"><span class="pre">port=</span></code> wins over a conflicting <code class="docutils literal notranslate"><span class="pre">PORT</span></code> environment variable.</p></li>
|
||
<li><p>Added <code class="docutils literal notranslate"><span class="pre">head()</span></code> and <code class="docutils literal notranslate"><span class="pre">options()</span></code> shortcut decorators on <code class="docutils literal notranslate"><span class="pre">API</span></code>, <code class="docutils literal notranslate"><span class="pre">RouteGroup</span></code>,
|
||
and standalone <code class="docutils literal notranslate"><span class="pre">Router</span></code> instances.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id8">
|
||
<h3>Changed<a class="headerlink" href="#id8" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Declared the Starlette test-client dependencies explicitly (<code class="docutils literal notranslate"><span class="pre">httpx</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">httpx2</span></code>), raised the Uvicorn and Granian dependency floors to current
|
||
compatible releases, and allowed Sphinx 9 for documentation builds.</p></li>
|
||
<li><p>Removed the PyPy classifier and remaining PyPy-specific test-extra guidance
|
||
now that future CI runs target CPython only.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v8-2-3-2026-07-05">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v8.2.2..v8.2.3">v8.2.3</a> - 2026-07-05<a class="headerlink" href="#v8-2-3-2026-07-05" title="Link to this heading">¶</a></h2>
|
||
<section id="id9">
|
||
<h3>Fixed<a class="headerlink" href="#id9" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">RedisSessionBackend</span></code> and <code class="docutils literal notranslate"><span class="pre">AsyncRedisSessionBackend</span></code> now write sessions with
|
||
Redis <code class="docutils literal notranslate"><span class="pre">SET</span></code> plus expiry (<code class="docutils literal notranslate"><span class="pre">EX</span></code>) when the client supports it, avoiding the
|
||
<code class="docutils literal notranslate"><span class="pre">setex</span></code> deprecation warning emitted by current redis-py/fakeredis while
|
||
preserving a fallback for older or custom clients that only expose <code class="docutils literal notranslate"><span class="pre">setex</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="documentation">
|
||
<h3>Documentation<a class="headerlink" href="#documentation" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Added a runnable examples guide, surfaced it in the sidebar navigation, and
|
||
linked the existing v6 migration guide from the project navigation.</p></li>
|
||
<li><p>Updated the docs Makefile so <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">html</span></code> uses the declared documentation
|
||
dependencies through <code class="docutils literal notranslate"><span class="pre">uv</span> <span class="pre">run</span> <span class="pre">--extra</span> <span class="pre">docs</span> <span class="pre">sphinx-build</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v8-2-2-2026-07-03">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v8.2.1..v8.2.2">v8.2.2</a> - 2026-07-03<a class="headerlink" href="#v8-2-2-2026-07-03" title="Link to this heading">¶</a></h2>
|
||
<section id="id10">
|
||
<h3>Fixed<a class="headerlink" href="#id10" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">RateLimiter.limit</span></code> now propagates the decorated handler’s return value, so
|
||
return-value-style handlers (<code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">{...}</span></code>, <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">text</span></code>, or
|
||
<code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">data,</span> <span class="pre">status[,</span> <span class="pre">headers]</span></code>) compose with the decorator. Previously the
|
||
wrapper discarded the return value in both the sync and async branches, so
|
||
any <code class="docutils literal notranslate"><span class="pre">@limiter.limit</span></code> handler that returned data instead of mutating <code class="docutils literal notranslate"><span class="pre">resp</span></code>
|
||
produced an empty <code class="docutils literal notranslate"><span class="pre">200</span></code> response. Mutation-style handlers were unaffected,
|
||
which is why it went unnoticed. The over-limit path is unchanged: a request
|
||
past the limit still gets a <code class="docutils literal notranslate"><span class="pre">429</span></code> with <code class="docutils literal notranslate"><span class="pre">Retry-After</span></code> and the handler is not
|
||
invoked.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v8-2-1-2026-07-03">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v8.2.0..v8.2.1">v8.2.1</a> - 2026-07-03<a class="headerlink" href="#v8-2-1-2026-07-03" title="Link to this heading">¶</a></h2>
|
||
<p>A security patch closing two response-injection gaps found by an adversarial
|
||
sweep over the non-auth framework surface (the auth extension was hardened in
|
||
8.2.0). Both fixes are defense-in-depth and change no legitimate behavior.</p>
|
||
<section id="security">
|
||
<h3>Security<a class="headerlink" href="#security" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Response header values are now stripped of CR, LF, and NUL before they reach
|
||
the ASGI layer, closing an HTTP response-splitting / header-injection vector.
|
||
A user-controlled value written to a header — most commonly a redirect target
|
||
via <code class="docutils literal notranslate"><span class="pre">Response.redirect(location)</span></code> or <code class="docutils literal notranslate"><span class="pre">Response.created(location=...)</span></code>, but also
|
||
any <code class="docutils literal notranslate"><span class="pre">resp.headers[...]</span> <span class="pre">=</span> <span class="pre">...</span></code> assignment — could previously carry a bare
|
||
<code class="docutils literal notranslate"><span class="pre">\r\n</span></code> onto the wire, letting an attacker inject additional response headers
|
||
(e.g. <code class="docutils literal notranslate"><span class="pre">Set-Cookie</span></code>) or split the response on ASGI servers/proxies that don’t
|
||
reject embedded control bytes. The framework already scrubbed CR/LF from
|
||
<code class="docutils literal notranslate"><span class="pre">Content-Disposition</span></code> and Server-Sent Events fields; this extends the same
|
||
discipline to every response header.</p></li>
|
||
<li><p>The access-log middleware (<code class="docutils literal notranslate"><span class="pre">responder.ext.logging</span></code>) now strips control
|
||
characters (C0 range and DEL) from the request method and path before logging
|
||
them. Because ASGI servers percent-decode <code class="docutils literal notranslate"><span class="pre">scope["path"]</span></code>, a request to a
|
||
path like <code class="docutils literal notranslate"><span class="pre">/x%0d%0a[INFO]...</span></code> previously wrote a raw CR/LF into the log line,
|
||
letting an attacker forge log records in a plaintext log sink. Spaces and
|
||
non-ASCII in a decoded path are preserved — only control bytes are removed —
|
||
mirroring the validation already applied to inbound <code class="docutils literal notranslate"><span class="pre">X-Request-ID</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v8-2-0-2026-07-03">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v8.1.0..v8.2.0">v8.2.0</a> - 2026-07-03<a class="headerlink" href="#v8-2-0-2026-07-03" title="Link to this heading">¶</a></h2>
|
||
<p>A security-focused release hardening the JWT/OAuth2 authentication introduced
|
||
in 8.1.0. A dedicated adversarial pass over the new auth code surfaced nine
|
||
issues (all in <code class="docutils literal notranslate"><span class="pre">responder.ext.auth</span></code>); every fix ships with a regression test.</p>
|
||
<section id="id11">
|
||
<h3>Security<a class="headerlink" href="#id11" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">JWTAuth</span></code> rejects a plaintext (<code class="docutils literal notranslate"><span class="pre">http</span></code>) <code class="docutils literal notranslate"><span class="pre">jwks_url</span></code> at construction unless it
|
||
targets loopback (<code class="docutils literal notranslate"><span class="pre">localhost</span></code>/<code class="docutils literal notranslate"><span class="pre">127.0.0.1</span></code>/<code class="docutils literal notranslate"><span class="pre">[::1]</span></code>) or <code class="docutils literal notranslate"><span class="pre">allow_insecure_jwks=True</span></code>
|
||
is passed. A man-in-the-middle on a plaintext JWKS fetch could serve
|
||
attacker-controlled signing keys — a full authentication bypass.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">JWTAuth</span></code> no longer lets an attacker-controlled, unknown <code class="docutils literal notranslate"><span class="pre">kid</span></code> amplify into
|
||
unbounded blocking JWKS refetches. The JWKS client now caches keys, and a
|
||
missing <code class="docutils literal notranslate"><span class="pre">kid</span></code> triggers at most one network refresh per short cooldown window
|
||
(otherwise rejecting with <code class="docutils literal notranslate"><span class="pre">401</span></code> and no fetch), closing an unauthenticated
|
||
denial-of-service vector. The JWKS cache is lock-guarded for the threadpool.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">JWTAuth</span></code> rejects tokens without an <code class="docutils literal notranslate"><span class="pre">exp</span></code> claim by default (new
|
||
<code class="docutils literal notranslate"><span class="pre">require_exp=True</span></code>); previously an expiry-less token was accepted
|
||
indefinitely. See the note under Changed to restore the old behavior.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">OAuth2Auth</span></code> no longer mutates token-introspection principals in place, and a
|
||
previously-stamped <code class="docutils literal notranslate"><span class="pre">scopes</span></code> value no longer short-circuits a fresh
|
||
introspection result — fixing privilege retention where a token that the
|
||
authorization server had downscoped kept its old, broader scopes.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id12">
|
||
<h3>Changed<a class="headerlink" href="#id12" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">JWTAuth(require_exp=...)</span></code> defaults to <code class="docutils literal notranslate"><span class="pre">True</span></code>, so tokens without an <code class="docutils literal notranslate"><span class="pre">exp</span></code>
|
||
claim are rejected. This is stricter than 8.1.0, which accepted them. If you
|
||
intentionally issue non-expiring JWTs, pass <code class="docutils literal notranslate"><span class="pre">require_exp=False</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id13">
|
||
<h3>Fixed<a class="headerlink" href="#id13" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">JWTAuth</span></code>: a JWKS-configured scheme no longer raises an uncaught <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>
|
||
(HTTP 500) when sent an <code class="docutils literal notranslate"><span class="pre">HS256</span></code> token whose <code class="docutils literal notranslate"><span class="pre">kid</span></code> resolves to a public key —
|
||
the mismatch now rejects with <code class="docutils literal notranslate"><span class="pre">401</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">JWTAuth</span></code>: <code class="docutils literal notranslate"><span class="pre">audience=None</span></code> now actually disables <code class="docutils literal notranslate"><span class="pre">aud</span></code> verification, so tokens
|
||
carrying an <code class="docutils literal notranslate"><span class="pre">aud</span></code> claim (virtually every OIDC access token) are accepted
|
||
instead of being rejected with <code class="docutils literal notranslate"><span class="pre">401</span></code>. When <code class="docutils literal notranslate"><span class="pre">audience</span></code> is set, it is still
|
||
enforced.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">JWTAuth</span></code>/<code class="docutils literal notranslate"><span class="pre">OAuth2Auth</span></code>: the <code class="docutils literal notranslate"><span class="pre">scope</span></code> and <code class="docutils literal notranslate"><span class="pre">scp</span></code> claims are now unioned rather
|
||
than the first-present one winning, so an Azure AD / Auth0 token that carries
|
||
its granted scopes in <code class="docutils literal notranslate"><span class="pre">scp</span></code> (with an empty <code class="docutils literal notranslate"><span class="pre">scope</span></code>) is no longer denied <code class="docutils literal notranslate"><span class="pre">403</span></code>.</p></li>
|
||
<li><p>OAuth2 flows: constructing a flow with an empty required URL
|
||
(<code class="docutils literal notranslate"><span class="pre">authorizationUrl</span></code>/<code class="docutils literal notranslate"><span class="pre">tokenUrl</span></code>) now raises <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> instead of silently
|
||
emitting an OpenAPI security scheme that fails validation.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="packaging">
|
||
<h3>Packaging<a class="headerlink" href="#packaging" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>The <code class="docutils literal notranslate"><span class="pre">orjson</span></code> and <code class="docutils literal notranslate"><span class="pre">fakeredis[lua]</span></code> test dependencies (compiled, without wheels
|
||
on free-threaded CPython or PyPy) moved out of the <code class="docutils literal notranslate"><span class="pre">test</span></code> extra into a
|
||
version-scoped CI step, so <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">responder[test]</span></code> on free-threaded
|
||
3.14 no longer fails trying to build them from source.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v8-1-0-2026-07-03">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v8.0.2..v8.1.0">v8.1.0</a> - 2026-07-03<a class="headerlink" href="#v8-1-0-2026-07-03" title="Link to this heading">¶</a></h2>
|
||
<section id="id14">
|
||
<h3>Added<a class="headerlink" href="#id14" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">JWTAuth</span></code> in <code class="docutils literal notranslate"><span class="pre">responder.ext.auth</span></code>: <code class="docutils literal notranslate"><span class="pre">Authorization:</span> <span class="pre">Bearer</span></code> authentication
|
||
with full JWT validation — signature (HS256 by default; RS256/ES256 and
|
||
friends when <code class="docutils literal notranslate"><span class="pre">cryptography</span></code> is installed), <code class="docutils literal notranslate"><span class="pre">exp</span></code>/<code class="docutils literal notranslate"><span class="pre">nbf</span></code>/<code class="docutils literal notranslate"><span class="pre">iat</span></code> with a
|
||
configurable <code class="docutils literal notranslate"><span class="pre">leeway</span></code>, and <code class="docutils literal notranslate"><span class="pre">audience</span></code>/<code class="docutils literal notranslate"><span class="pre">issuer</span></code> checks. Keys come from a
|
||
static <code class="docutils literal notranslate"><span class="pre">secret</span></code> (HMAC secret or PEM public key) or a <code class="docutils literal notranslate"><span class="pre">jwks_url</span></code>, resolved by
|
||
the token’s <code class="docutils literal notranslate"><span class="pre">kid</span></code> header with cached key sets that refresh automatically on
|
||
rotation (the JWKS fetch runs off the event loop). The validated claims
|
||
become the injected principal — or pass <code class="docutils literal notranslate"><span class="pre">verify=</span></code> to map them onto your own
|
||
user object — and the token’s <code class="docutils literal notranslate"><span class="pre">scope</span></code>/<code class="docutils literal notranslate"><span class="pre">scp</span></code> claim is normalized into the
|
||
scopes that feed <code class="docutils literal notranslate"><span class="pre">requires()</span></code>. Invalid tokens reject with <code class="docutils literal notranslate"><span class="pre">401</span></code> + a <code class="docutils literal notranslate"><span class="pre">Bearer</span></code>
|
||
challenge, missing scopes with <code class="docutils literal notranslate"><span class="pre">403</span></code> + <code class="docutils literal notranslate"><span class="pre">insufficient_scope</span></code>. Requires the new
|
||
<code class="docutils literal notranslate"><span class="pre">responder[jwt]</span></code> extra (PyJWT), imported lazily with a helpful error.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">OAuth2Auth</span></code> and flow descriptions (<code class="docutils literal notranslate"><span class="pre">OAuth2AuthorizationCodeFlow</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">OAuth2ClientCredentialsFlow</span></code>, <code class="docutils literal notranslate"><span class="pre">OAuth2PasswordFlow</span></code>) in <code class="docutils literal notranslate"><span class="pre">responder.ext.auth</span></code>:
|
||
the OpenAPI document emits a proper <code class="docutils literal notranslate"><span class="pre">type:</span> <span class="pre">oauth2</span></code> security scheme with flows
|
||
and scopes, lighting up Swagger UI’s Authorize button. At runtime it acts as
|
||
a resource server — bearer tokens are validated locally through a <code class="docutils literal notranslate"><span class="pre">jwt=</span></code>
|
||
<code class="docutils literal notranslate"><span class="pre">JWTAuth</span></code> or a <code class="docutils literal notranslate"><span class="pre">verify=</span></code> token-introspection callable. Convenience
|
||
constructors <code class="docutils literal notranslate"><span class="pre">OAuth2Auth.authorization_code(...)</span></code>, <code class="docutils literal notranslate"><span class="pre">.client_credentials(...)</span></code>,
|
||
and <code class="docutils literal notranslate"><span class="pre">.password(...)</span></code> cover the single-flow cases; both compose with
|
||
<code class="docutils literal notranslate"><span class="pre">requires()</span></code>/<code class="docutils literal notranslate"><span class="pre">optional()</span></code>/<code class="docutils literal notranslate"><span class="pre">AuthPolicy</span></code> and group-level auth via
|
||
<code class="docutils literal notranslate"><span class="pre">Router</span></code>/<code class="docutils literal notranslate"><span class="pre">include_router</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">responder.Problem</span></code> — a raisable RFC 9457 problem-details exception. Raise
|
||
<code class="docutils literal notranslate"><span class="pre">Problem(409,</span> <span class="pre">"detail",</span> <span class="pre">title=...,</span> <span class="pre">type=...,</span> <span class="pre">instance=...,</span> <span class="pre">**extensions)</span></code>
|
||
from any view, hook, or dependency to short-circuit with a full
|
||
<code class="docutils literal notranslate"><span class="pre">application/problem+json</span></code> response, rendered through the same pipeline as
|
||
framework errors (<code class="docutils literal notranslate"><span class="pre">problem_handler</span></code> enrichment, request IDs, the app’s JSON
|
||
encoder). <code class="docutils literal notranslate"><span class="pre">instance</span></code> defaults to the request path, and because it subclasses
|
||
Starlette’s <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code>, existing handlers and middleware treat it like
|
||
<code class="docutils literal notranslate"><span class="pre">abort()</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">abort()</span></code> now accepts the RFC 9457 members — <code class="docutils literal notranslate"><span class="pre">title=</span></code>, <code class="docutils literal notranslate"><span class="pre">type=</span></code>, <code class="docutils literal notranslate"><span class="pre">instance=</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">errors=</span></code>, and arbitrary extension keywords — raising a <code class="docutils literal notranslate"><span class="pre">Problem</span></code> that
|
||
carries them into the payload. Plain <code class="docutils literal notranslate"><span class="pre">abort(status,</span> <span class="pre">detail=...,</span> <span class="pre">headers=...)</span></code>
|
||
still raises a regular <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code>, unchanged.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">@api.middleware("http")</span></code> — a decorator for function-style HTTP middleware:
|
||
<code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span> <span class="pre">mw(request,</span> <span class="pre">call_next)</span> <span class="pre">-></span> <span class="pre">response</span></code>, no ASGI class boilerplate.
|
||
Synchronous functions run on a dedicated thread pool and receive a blocking
|
||
<code class="docutils literal notranslate"><span class="pre">call_next</span></code>. Function middleware registers through the same stack as
|
||
<code class="docutils literal notranslate"><span class="pre">add_middleware</span></code>, so the two compose: the most-recently-registered user
|
||
middleware is outermost. Backed by the new public
|
||
<code class="docutils literal notranslate"><span class="pre">responder.middleware.FunctionMiddleware</span></code> adapter; WebSocket and lifespan
|
||
traffic pass through untouched.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">req.headers.get_list("X-Forwarded-For")</span></code> returns every raw line of a
|
||
repeated request header, in the order received — duplicate header lines are
|
||
no longer silently collapsed. Single-value access is unchanged: last wins.</p></li>
|
||
<li><p>Write-side HTTP preconditions (RFC 9110 §13): on state-changing methods,
|
||
when <code class="docutils literal notranslate"><span class="pre">resp.etag</span></code> or <code class="docutils literal notranslate"><span class="pre">resp.last_modified</span></code> is set, <code class="docutils literal notranslate"><span class="pre">If-Match</span></code> (strong
|
||
comparison, <code class="docutils literal notranslate"><span class="pre">*</span></code> supported), <code class="docutils literal notranslate"><span class="pre">If-Unmodified-Since</span></code> (only when <code class="docutils literal notranslate"><span class="pre">If-Match</span></code> is
|
||
absent), and <code class="docutils literal notranslate"><span class="pre">If-None-Match</span></code> are evaluated, and a failing precondition
|
||
answers <code class="docutils literal notranslate"><span class="pre">412</span> <span class="pre">Precondition</span> <span class="pre">Failed</span></code>. Repeated header lines are folded per the
|
||
RFC. Like the existing <code class="docutils literal notranslate"><span class="pre">304</span></code> handling, preconditions are checked only when
|
||
the matching validator is set.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">req.preferred_media_type(candidates)</span></code> — ranks candidate media types (or
|
||
bare subtype tokens) by the q-value of the most specific matching <code class="docutils literal notranslate"><span class="pre">Accept</span></code>
|
||
range and returns the client’s preferred one, or <code class="docutils literal notranslate"><span class="pre">None</span></code> when it accepts
|
||
none. Ties, and requests without an <code class="docutils literal notranslate"><span class="pre">Accept</span></code> header, keep the candidate
|
||
order.</p></li>
|
||
<li><p>Pydantic body-model injection for class-based views:
|
||
<code class="docutils literal notranslate"><span class="pre">on_post(self,</span> <span class="pre">req,</span> <span class="pre">resp,</span> <span class="pre">*,</span> <span class="pre">item:</span> <span class="pre">Item)</span></code> receives the parsed, validated
|
||
body exactly like function views (automatic <code class="docutils literal notranslate"><span class="pre">422</span></code> on invalid input). The
|
||
body is parsed once per request, so <code class="docutils literal notranslate"><span class="pre">on_request</span></code> and a method handler
|
||
declaring the same model share one validated instance.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">Query()</span></code>, <code class="docutils literal notranslate"><span class="pre">Header()</span></code>, <code class="docutils literal notranslate"><span class="pre">Cookie()</span></code>, and <code class="docutils literal notranslate"><span class="pre">Path()</span></code> markers now resolve on
|
||
WebSocket handlers from the handshake request (query string, headers,
|
||
cookies), with the same Pydantic coercion as HTTP views. A missing required
|
||
value or failed coercion closes the socket with <code class="docutils literal notranslate"><span class="pre">1008</span></code> (policy violation)
|
||
before the handler runs.</p></li>
|
||
<li><p>Bind an entire form to a Pydantic model: a parameter annotated with a
|
||
<code class="docutils literal notranslate"><span class="pre">BaseModel</span></code> subclass and a <code class="docutils literal notranslate"><span class="pre">Form(...)</span></code> default validates the parsed
|
||
urlencoded/multipart form into the model in one shot — repeated keys collect
|
||
into list fields, uploads bind to <code class="docutils literal notranslate"><span class="pre">UploadFile</span></code> fields, aliases are honored,
|
||
and failures return the same <code class="docutils literal notranslate"><span class="pre">422</span></code> payload as JSON body models with
|
||
<code class="docutils literal notranslate"><span class="pre">["form",</span> <span class="pre"><field>]</span></code> error locations. The OpenAPI schema documents the model
|
||
as the <code class="docutils literal notranslate"><span class="pre">multipart/form-data</span></code>/<code class="docutils literal notranslate"><span class="pre">application/x-www-form-urlencoded</span></code> requestBody.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">RateLimiter</span></code> accepts <code class="docutils literal notranslate"><span class="pre">key=</span></code> — a callable <code class="docutils literal notranslate"><span class="pre">req</span> <span class="pre">-></span> <span class="pre">str</span></code> naming the bucket a
|
||
request counts against (an API key, a user id) instead of the client IP
|
||
(still the default and the fallback) — and <code class="docutils literal notranslate"><span class="pre">fail_open=</span></code>: when the backend
|
||
errors out (e.g. Redis is unreachable), <code class="docutils literal notranslate"><span class="pre">fail_open=True</span></code> logs a warning and
|
||
lets the request through, while the default <code class="docutils literal notranslate"><span class="pre">False</span></code> answers <code class="docutils literal notranslate"><span class="pre">503</span></code> instead of
|
||
an unhandled 500. Every response now carries <code class="docutils literal notranslate"><span class="pre">X-RateLimit-Reset</span></code>; the backend
|
||
<code class="docutils literal notranslate"><span class="pre">hit()</span></code>/<code class="docutils literal notranslate"><span class="pre">ahit()</span></code> contract grew a third <code class="docutils literal notranslate"><span class="pre">reset_after</span></code> element, with 2-tuple
|
||
third-party backends still accepted (the header is omitted).</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">MetricsCollector</span></code> accepts <code class="docutils literal notranslate"><span class="pre">buckets=</span></code> — ascending histogram bucket bounds —
|
||
exposed as <code class="docutils literal notranslate"><span class="pre">API(metrics_buckets=...)</span></code>, and <code class="docutils literal notranslate"><span class="pre">/metrics</span></code> now exports a
|
||
<code class="docutils literal notranslate"><span class="pre">responder_requests_in_flight</span></code> gauge.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">responder.ext.pagination.set_pagination_headers(req,</span> <span class="pre">resp,</span> <span class="pre">page)</span></code> emits the
|
||
RFC 8288 <code class="docutils literal notranslate"><span class="pre">Link</span></code> header (<code class="docutils literal notranslate"><span class="pre">rel="first"</span></code>/<code class="docutils literal notranslate"><span class="pre">"prev"</span></code>/<code class="docutils literal notranslate"><span class="pre">"next"</span></code>/<code class="docutils literal notranslate"><span class="pre">"last"</span></code>, built from
|
||
the request URL with all other query parameters preserved) plus
|
||
<code class="docutils literal notranslate"><span class="pre">X-Total-Count</span></code>, alongside the existing <code class="docutils literal notranslate"><span class="pre">Page</span></code> body envelope.</p></li>
|
||
<li><p>CLI: <code class="docutils literal notranslate"><span class="pre">responder</span> <span class="pre">run</span></code> accepts <code class="docutils literal notranslate"><span class="pre">--host=<addr></span></code>, <code class="docutils literal notranslate"><span class="pre">--port=<n></span></code>, and
|
||
<code class="docutils literal notranslate"><span class="pre">--server=<name></span></code> (<code class="docutils literal notranslate"><span class="pre">uvicorn</span></code> or <code class="docutils literal notranslate"><span class="pre">granian</span></code>) to control binding and backend,
|
||
plus <code class="docutils literal notranslate"><span class="pre">--reload</span></code> for uvicorn auto-reload (requires a <code class="docutils literal notranslate"><span class="pre">module:attr</span></code> target).</p></li>
|
||
<li><p>Optional orjson JSON backend: when orjson is installed
|
||
(<code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">"responder[orjson]"</span></code>), JSON responses encode via orjson —
|
||
typically several times faster, with less event-loop blocking. Custom
|
||
<code class="docutils literal notranslate"><span class="pre">API(encoder=...)</span></code> hooks keep working, and <code class="docutils literal notranslate"><span class="pre">json_ensure_ascii=True</span></code> stays on
|
||
the stdlib (orjson is UTF-8-only). Decoding continues to use the stdlib so
|
||
arbitrary-precision integers stay exact. Encoded output differs only in
|
||
whitespace, except float <code class="docutils literal notranslate"><span class="pre">nan</span></code>/<code class="docutils literal notranslate"><span class="pre">inf</span></code> serialize as <code class="docutils literal notranslate"><span class="pre">null</span></code> instead of the
|
||
non-standard <code class="docutils literal notranslate"><span class="pre">NaN</span></code>/<code class="docutils literal notranslate"><span class="pre">Infinity</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">responder.testing.AsyncTestClient</span></code>: the async mirror of <code class="docutils literal notranslate"><span class="pre">api.requests</span></code> — an
|
||
<code class="docutils literal notranslate"><span class="pre">httpx.AsyncClient</span></code> dispatching in-process; <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">with</span></code> runs the app’s
|
||
lifespan. Backed by <code class="docutils literal notranslate"><span class="pre">ASGIStreamingTransport</span></code>, which streams response bodies
|
||
live, so endless SSE streams can be read and closed mid-flight.</p></li>
|
||
<li><p>SSE test helpers in <code class="docutils literal notranslate"><span class="pre">responder.testing</span></code>: <code class="docutils literal notranslate"><span class="pre">parse_sse(text)</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">iter_sse(response)</span></code>, and <code class="docutils literal notranslate"><span class="pre">collect_sse(response)</span></code> parse <code class="docutils literal notranslate"><span class="pre">text/event-stream</span></code>
|
||
bodies into <code class="docutils literal notranslate"><span class="pre">SSEEvent</span></code> objects (<code class="docutils literal notranslate"><span class="pre">data</span></code>/<code class="docutils literal notranslate"><span class="pre">event</span></code>/<code class="docutils literal notranslate"><span class="pre">id</span></code>/<code class="docutils literal notranslate"><span class="pre">retry</span></code>, plus <code class="docutils literal notranslate"><span class="pre">.json()</span></code>),
|
||
skipping heartbeat comments — the client-side mirror of <code class="docutils literal notranslate"><span class="pre">resp.sse</span></code>.</p></li>
|
||
<li><p>Test coverage for the Redis session and rate-limit backends against
|
||
<code class="docutils literal notranslate"><span class="pre">fakeredis</span></code> (sync and async, including the atomic INCR+EXPIRE Lua script),
|
||
covering TTL/expiry, key prefixes, middleware round-trips, and outage
|
||
behavior.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">status_code=</span></code> route option: <code class="docutils literal notranslate"><span class="pre">@api.route("/items",</span> <span class="pre">methods=["POST"],</span> <span class="pre">status_code=201)</span></code> pre-seeds <code class="docutils literal notranslate"><span class="pre">resp.status_code</span></code> (an explicit assignment in
|
||
the view still wins) and documents the success response under that status in
|
||
the OpenAPI operation instead of a hardcoded <code class="docutils literal notranslate"><span class="pre">200</span></code>. Works with the method
|
||
sugar, <code class="docutils literal notranslate"><span class="pre">api.group()</span></code>, and standalone <code class="docutils literal notranslate"><span class="pre">responder.Router</span></code> declarations.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id15">
|
||
<h3>Changed<a class="headerlink" href="#id15" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Content negotiation honors the client’s q-ranked <code class="docutils literal notranslate"><span class="pre">Accept</span></code> preference order
|
||
when a response could serialize to multiple registered formats, instead of
|
||
always serving the first registered format:
|
||
<code class="docutils literal notranslate"><span class="pre">Accept:</span> <span class="pre">application/yaml;q=0.9,</span> <span class="pre">application/json;q=0.1</span></code> now gets YAML where
|
||
it previously got JSON. Behavior changes only when a client explicitly ranks
|
||
formats — spec-correct per RFC 9110 §12.5.1; without an <code class="docutils literal notranslate"><span class="pre">Accept</span></code> header (or
|
||
when everything ties) JSON remains the default.</p></li>
|
||
<li><p>Class-based views now auto-answer <code class="docutils literal notranslate"><span class="pre">OPTIONS</span></code>. A CBV that defines neither
|
||
<code class="docutils literal notranslate"><span class="pre">on_options</span></code> nor <code class="docutils literal notranslate"><span class="pre">on_request</span></code> responds to <code class="docutils literal notranslate"><span class="pre">OPTIONS</span></code> with <code class="docutils literal notranslate"><span class="pre">200</span></code> and an
|
||
<code class="docutils literal notranslate"><span class="pre">Allow</span></code> header listing the methods it serves, instead of <code class="docutils literal notranslate"><span class="pre">405</span></code> — the same
|
||
treatment method-restricted function routes already got (RFC 9110 §9.3.7).
|
||
The <code class="docutils literal notranslate"><span class="pre">Allow</span></code> header on a CBV’s <code class="docutils literal notranslate"><span class="pre">405</span></code> response now includes <code class="docutils literal notranslate"><span class="pre">OPTIONS</span></code> too,
|
||
keeping the advertised methods consistent between the two paths.</p></li>
|
||
<li><p>Class-based views now reject unsupported HTTP methods with <code class="docutils literal notranslate"><span class="pre">405</span></code> <em>before</em>
|
||
validating typed parameters, so a request using a method the CBV does not
|
||
serve gets <code class="docutils literal notranslate"><span class="pre">405</span></code> (with <code class="docutils literal notranslate"><span class="pre">Allow</span></code>) rather than a <code class="docutils literal notranslate"><span class="pre">422</span></code> from a handler that would
|
||
never run — matching how function routes have always ordered method dispatch
|
||
and parameter validation. Supported methods still validate and return <code class="docutils literal notranslate"><span class="pre">422</span></code>
|
||
on bad input.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">RequestIDMiddleware</span></code> and <code class="docutils literal notranslate"><span class="pre">LoggingMiddleware</span></code> now share one request-ID
|
||
policy: an inbound <code class="docutils literal notranslate"><span class="pre">X-Request-ID</span></code> is honored when it is at most 128 printable
|
||
ASCII characters (<code class="docutils literal notranslate"><span class="pre">\x21</span></code>–<code class="docutils literal notranslate"><span class="pre">\x7e</span></code>, so namespaced ids like <code class="docutils literal notranslate"><span class="pre">gateway:abc123</span></code> and
|
||
base64-flavored ids pass, while control characters and oversized values are
|
||
replaced to prevent header/log injection and bloat), and both mint full
|
||
UUID4s
|
||
otherwise — <code class="docutils literal notranslate"><span class="pre">LoggingMiddleware</span></code> previously minted 8-hex-char ids (32 bits of
|
||
entropy), so a busy fleet risked collisions and flipping <code class="docutils literal notranslate"><span class="pre">enable_logging</span></code>
|
||
changed the ID format. <code class="docutils literal notranslate"><span class="pre">setup_logging</span></code> is now exported in <code class="docutils literal notranslate"><span class="pre">__all__</span></code>.</p></li>
|
||
<li><p>Coverage is now enforced (<code class="docutils literal notranslate"><span class="pre">fail_under</span> <span class="pre">=</span> <span class="pre">80</span></code>, previously 0) and measures only
|
||
the <code class="docutils literal notranslate"><span class="pre">responder</span></code> package, so generated clientgen artifacts and <code class="docutils literal notranslate"><span class="pre">examples/*.py</span></code>
|
||
no longer pollute the report.</p></li>
|
||
<li><p>The generated OpenAPI document is cached instead of rebuilt on every request
|
||
to the schema route or docs page; registering a route, schema, or security
|
||
scheme invalidates the cache.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id16">
|
||
<h3>Fixed<a class="headerlink" href="#id16" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Session values that work with <code class="docutils literal notranslate"><span class="pre">MemorySessionBackend</span></code> — <code class="docutils literal notranslate"><span class="pre">datetime</span></code>, <code class="docutils literal notranslate"><span class="pre">date</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">time</span></code>, <code class="docutils literal notranslate"><span class="pre">Decimal</span></code>, <code class="docutils literal notranslate"><span class="pre">UUID</span></code>, <code class="docutils literal notranslate"><span class="pre">set</span></code>, <code class="docutils literal notranslate"><span class="pre">frozenset</span></code>, <code class="docutils literal notranslate"><span class="pre">bytes</span></code> — no longer crash the
|
||
Redis session backends with a hard-to-debug 500: the new default
|
||
<code class="docutils literal notranslate"><span class="pre">JSONSessionSerializer</span></code> round-trips those types (and refuses user data that
|
||
collides with its reserved type tag), and a <code class="docutils literal notranslate"><span class="pre">serializer=</span></code> parameter accepts
|
||
any custom <code class="docutils literal notranslate"><span class="pre">dumps</span></code>/<code class="docutils literal notranslate"><span class="pre">loads</span></code> codec. The storable-values contract is documented
|
||
for all backends.</p></li>
|
||
<li><p>Prometheus <code class="docutils literal notranslate"><span class="pre">/metrics</span></code> output escapes backslashes, double quotes, and
|
||
newlines in label values per the exposition format, so a route pattern
|
||
containing them can no longer break the whole scrape. The <code class="docutils literal notranslate"><span class="pre">RateLimiter</span></code>
|
||
docstring no longer claims “token bucket” (the memory backend is a sliding
|
||
window; the Redis backends are fixed-window).</p></li>
|
||
<li><p>Registering two <em>different</em> security schemes under the same name now raises
|
||
instead of silently overwriting (idempotent re-registration of the same
|
||
scheme, which routing performs per route, is still fine).</p></li>
|
||
<li><p>CLI: bare <code class="docutils literal notranslate"><span class="pre">responder</span></code> with no subcommand prints the usage summary and exits
|
||
non-zero instead of silently exiting <code class="docutils literal notranslate"><span class="pre">0</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="deprecated">
|
||
<h3>Deprecated<a class="headerlink" href="#deprecated" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API.session()</span></code> — use the <code class="docutils literal notranslate"><span class="pre">api.requests</span></code> property. Emits a
|
||
<code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code>; removal in 9.0.</p></li>
|
||
<li><p>The <code class="docutils literal notranslate"><span class="pre">PORT</span></code> environment variable overriding an explicitly passed <code class="docutils literal notranslate"><span class="pre">port=</span></code> in
|
||
<code class="docutils literal notranslate"><span class="pre">serve()</span></code>/<code class="docutils literal notranslate"><span class="pre">run()</span></code>. Warns only when both are set and differ; the environment
|
||
variable still wins until 9.0, when explicit <code class="docutils literal notranslate"><span class="pre">port=</span></code> will take precedence.</p></li>
|
||
<li><p>Calling <code class="docutils literal notranslate"><span class="pre">add_route()</span></code> without an endpoint (implicitly registering a
|
||
static-fallback route). Pass an endpoint explicitly (with <code class="docutils literal notranslate"><span class="pre">default=True</span></code> for
|
||
a catch-all); the implicit behavior is removed in 9.0.</p></li>
|
||
<li><p>Lossy <code class="docutils literal notranslate"><span class="pre">decimal.Decimal</span></code>-to-float JSON serialization. Warns once per process
|
||
when a bare <code class="docutils literal notranslate"><span class="pre">Decimal</span></code> reaches the built-in encoder; 9.0 will serialize
|
||
<code class="docutils literal notranslate"><span class="pre">Decimal</span></code> as strings. Convert explicitly or pass a custom <code class="docutils literal notranslate"><span class="pre">encoder=</span></code>.</p></li>
|
||
<li><p>GraphQL responses returning HTTP 400 when the result contains partial data
|
||
alongside errors. Warns once per process; 9.0 will return 200 for such
|
||
responses per the GraphQL-over-HTTP spec (no-data error responses keep 400).</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v8-0-2-2026-07-03">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v8.0.1..v8.0.2">v8.0.2</a> - 2026-07-03<a class="headerlink" href="#v8-0-2-2026-07-03" title="Link to this heading">¶</a></h2>
|
||
<section id="id17">
|
||
<h3>Fixed<a class="headerlink" href="#id17" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">ResponderServer</span></code>’s private process-termination method no longer shadows
|
||
<code class="docutils literal notranslate"><span class="pre">threading.Thread._stop()</span></code>. On Python ≤ 3.12 and PyPy, <code class="docutils literal notranslate"><span class="pre">Thread.join()</span></code> calls
|
||
<code class="docutils literal notranslate"><span class="pre">self._stop()</span></code> internally, so joining a <code class="docutils literal notranslate"><span class="pre">ResponderServer</span></code> invoked the
|
||
process-termination logic (marking the server as stopping and skipping the
|
||
Thread’s own bookkeeping) instead of just waiting. Python 3.13+ was
|
||
unaffected. Latent since the class was introduced; surfaced by the 8.0.1
|
||
signal-handler restore tests.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v8-0-1-2026-07-02">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v8.0.0..v8.0.1">v8.0.1</a> - 2026-07-02<a class="headerlink" href="#v8-0-1-2026-07-02" title="Link to this heading">¶</a></h2>
|
||
<section id="id18">
|
||
<h3>Added<a class="headerlink" href="#id18" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>A “Migrating to v8” guide in the documentation, covering every 8.0 breaking
|
||
change with before/after examples — implicit <code class="docutils literal notranslate"><span class="pre">static/</span></code> removal,
|
||
<code class="docutils literal notranslate"><span class="pre">RouteNotFoundError</span></code> and percent-encoding in <code class="docutils literal notranslate"><span class="pre">url_for</span></code>, the 307 redirect
|
||
default, text-response charsets, <code class="docutils literal notranslate"><span class="pre">application/yaml</span></code>, empty-YAML-body 400s,
|
||
and the new dependency declarations and floors — plus a pointer to the
|
||
standalone-routers guide.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id19">
|
||
<h3>Fixed<a class="headerlink" href="#id19" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Trailing-slash redirects no longer crash on non-latin-1 paths: the
|
||
<code class="docutils literal notranslate"><span class="pre">Location</span></code> header is percent-encoded (<code class="docutils literal notranslate"><span class="pre">GET</span> <span class="pre">/日本/</span></code> now answers <code class="docutils literal notranslate"><span class="pre">307</span></code> instead
|
||
of a 500 from a <code class="docutils literal notranslate"><span class="pre">UnicodeEncodeError</span></code>), and the redirect now matches the
|
||
alternate path regardless of request method — <code class="docutils literal notranslate"><span class="pre">POST</span> <span class="pre">/page/</span></code> redirects to
|
||
<code class="docutils literal notranslate"><span class="pre">/page</span></code> just like GET does, instead of falling through to a 404.</p></li>
|
||
<li><p>A sync view that outlives <code class="docutils literal notranslate"><span class="pre">request_timeout</span></code> can no longer corrupt the
|
||
<code class="docutils literal notranslate"><span class="pre">504</span> <span class="pre">Gateway</span> <span class="pre">Timeout</span></code> response: the timeout reply is built on a fresh
|
||
<code class="docutils literal notranslate"><span class="pre">Response</span></code>, so the abandoned thread’s late writes land on an inert object.
|
||
Headers and cookies set by completed <code class="docutils literal notranslate"><span class="pre">before_request</span></code> hooks (request IDs,
|
||
CORS) are carried onto the 504; stale body-framing headers are not.</p></li>
|
||
<li><p>The route-resolution cache evicts its least-recently-used entry when full
|
||
instead of clearing all 1024 entries wholesale, so high-cardinality
|
||
parameterized paths no longer periodically wipe the hot static entries.</p></li>
|
||
<li><p>Route registration errors are real exceptions instead of <code class="docutils literal notranslate"><span class="pre">assert</span></code> statements
|
||
(which vanish under <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-O</span></code>): a route path without a leading <code class="docutils literal notranslate"><span class="pre">/</span></code>, an
|
||
unknown path convertor, and an unknown event type all raise <code class="docutils literal notranslate"><span class="pre">ValueError</span></code>
|
||
naming the offender, and a duplicate path parameter (<code class="docutils literal notranslate"><span class="pre">/x/{id}/{id}</span></code>) is
|
||
caught up front with a clear message instead of a bare <code class="docutils literal notranslate"><span class="pre">re.error</span></code>.</p></li>
|
||
<li><p>The legacy <code class="docutils literal notranslate"><span class="pre">on_event("shutdown")</span></code> lifespan path now mirrors the <code class="docutils literal notranslate"><span class="pre">lifespan=</span></code>
|
||
path when a shutdown handler raises: app-scoped dependency teardowns still
|
||
run and <code class="docutils literal notranslate"><span class="pre">lifespan.shutdown.failed</span></code> is sent, instead of both being skipped.</p></li>
|
||
<li><p>Class-based-view 405 responses now include the <code class="docutils literal notranslate"><span class="pre">Allow</span></code> header required by
|
||
RFC 9110 §15.5.6, listing the methods the class actually serves via <code class="docutils literal notranslate"><span class="pre">on_*</span></code>
|
||
handlers (plus implicit <code class="docutils literal notranslate"><span class="pre">HEAD</span></code> when <code class="docutils literal notranslate"><span class="pre">on_get</span></code> exists).</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">QueryDict</span></code> item assignment and <code class="docutils literal notranslate"><span class="pre">update()</span></code> no longer corrupt single-value
|
||
reads: assigning a scalar (<code class="docutils literal notranslate"><span class="pre">qd["x"]</span> <span class="pre">=</span> <span class="pre">"hello"</span></code>) previously stored a bare
|
||
string, so reading it back returned the last character. Scalars are stored
|
||
as one-element lists, and <code class="docutils literal notranslate"><span class="pre">update()</span></code> from another <code class="docutils literal notranslate"><span class="pre">QueryDict</span></code> merges the
|
||
full multi-value lists, matching 8.0.0 semantics.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">req.accepts()</span></code> honors media-range specificity per RFC 9110 §12.5.1: an
|
||
explicit <code class="docutils literal notranslate"><span class="pre">q=0</span></code> range now excludes the type even when a broader range
|
||
(<code class="docutils literal notranslate"><span class="pre">*/*</span></code> or <code class="docutils literal notranslate"><span class="pre">type/*</span></code>) would match — and a <code class="docutils literal notranslate"><span class="pre">q=0</span></code> wildcard of a <em>different</em>
|
||
top-level type no longer vetoes unrelated bare-token lookups.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">req.apparent_encoding</span></code> recognizes valid UTF-8 bodies with a cheap strict
|
||
decode and runs chardet detection in a worker thread, so a large body
|
||
without a <code class="docutils literal notranslate"><span class="pre">charset=</span></code> parameter no longer stalls the event loop.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.stream_file()</span></code> and <code class="docutils literal notranslate"><span class="pre">resp.download()</span></code> now send <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code>
|
||
(computed exactly for full-body, single-range, and multipart byte-range
|
||
responses). Replacing the body afterwards (<code class="docutils literal notranslate"><span class="pre">resp.text</span></code>, <code class="docutils literal notranslate"><span class="pre">resp.problem()</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">resp.created()</span></code>) clears the stale <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code>/<code class="docutils literal notranslate"><span class="pre">Content-Range</span></code>/
|
||
<code class="docutils literal notranslate"><span class="pre">Accept-Ranges</span></code> so the response cannot be misframed.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">HEAD</span></code> requests against <code class="docutils literal notranslate"><span class="pre">resp.file()</span></code> no longer read the entire file in the
|
||
threadpool just to discard the body — the headers (including the
|
||
stat-derived <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code>) are sent without touching the file contents.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.problem()</span></code> serializes extension members through the same type-aware
|
||
JSON encoder as <code class="docutils literal notranslate"><span class="pre">resp.media</span></code> (datetimes, UUIDs, Decimals, sets, dataclasses,
|
||
Pydantic models, and any custom <code class="docutils literal notranslate"><span class="pre">API(encoder=...)</span></code>) instead of bare
|
||
<code class="docutils literal notranslate"><span class="pre">json.dumps</span></code>, so <code class="docutils literal notranslate"><span class="pre">resp.problem(409,</span> <span class="pre">occurred_at=datetime.now())</span></code> no longer
|
||
turns into a 500.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.stream()</span></code> and <code class="docutils literal notranslate"><span class="pre">resp.sse()</span></code> raise a descriptive <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> when given
|
||
a non-async-generator function, instead of a message-less <code class="docutils literal notranslate"><span class="pre">assert</span></code> that
|
||
vanished under <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-O</span></code>.</p></li>
|
||
<li><p>OpenAPI parameter schemas for enum and nested Pydantic types no longer emit
|
||
dangling <code class="docutils literal notranslate"><span class="pre">$ref</span></code>s or inline <code class="docutils literal notranslate"><span class="pre">$defs</span></code>: referenced definitions are hoisted into
|
||
<code class="docutils literal notranslate"><span class="pre">components/schemas</span></code> (same-named models from different modules get distinct
|
||
component names) and the generated document passes <code class="docutils literal notranslate"><span class="pre">openapi-spec-validator</span></code>.</p></li>
|
||
<li><p>Generated clients (Python, JavaScript, TypeScript, Ruby, PHP) now actually
|
||
send the header and cookie parameters they accept.</p></li>
|
||
<li><p>Generated clients send <code class="docutils literal notranslate"><span class="pre">Form()</span></code>/<code class="docutils literal notranslate"><span class="pre">File()</span></code> request bodies as
|
||
<code class="docutils literal notranslate"><span class="pre">application/x-www-form-urlencoded</span></code> or <code class="docutils literal notranslate"><span class="pre">multipart/form-data</span></code> per the
|
||
documented requestBody media type, instead of JSON the server rejected with
|
||
422 — in every supported client language. Ruby multipart parts carry proper
|
||
filenames (with a <code class="docutils literal notranslate"><span class="pre">[filename,</span> <span class="pre">content]</span></code> pair form), and the PHP client
|
||
distinguishes file specs from plain list values.</p></li>
|
||
<li><p>WebSocket routes are no longer documented as HTTP GET operations in the
|
||
OpenAPI schema.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API(docs_route=...)</span></code> without <code class="docutils literal notranslate"><span class="pre">openapi=</span></code> now enables schema generation
|
||
(defaulting to OpenAPI 3.1.0) as documented, instead of serving a docs page
|
||
pointing at a 404 schema. An app that already registered its own route at
|
||
the schema path keeps it — the implied route is skipped with a warning.</p></li>
|
||
<li><p>Required JSON and form request bodies are marked <code class="docutils literal notranslate"><span class="pre">required:</span> <span class="pre">true</span></code> in the
|
||
OpenAPI schema, so generated clients require the body instead of defaulting
|
||
it to <code class="docutils literal notranslate"><span class="pre">None</span></code> and always failing at runtime.</p></li>
|
||
<li><p>The client generators emit correct code on parameter-name collisions
|
||
(<code class="docutils literal notranslate"><span class="pre">user-id</span></code> vs <code class="docutils literal notranslate"><span class="pre">user_id</span></code>, or parameters named <code class="docutils literal notranslate"><span class="pre">body</span></code>/<code class="docutils literal notranslate"><span class="pre">path</span></code>/<code class="docutils literal notranslate"><span class="pre">quote</span></code>):
|
||
deduplication and reserved-identifier handling are applied consistently to
|
||
signatures, query/header/cookie maps, and path interpolation in all four
|
||
generators.</p></li>
|
||
<li><p>Optional sequence query parameters (<code class="docutils literal notranslate"><span class="pre">tags:</span> <span class="pre">list[int]</span> <span class="pre">|</span> <span class="pre">None</span> <span class="pre">=</span> <span class="pre">Query(None)</span></code>)
|
||
now bind repeated values as a list instead of returning 422 — marker
|
||
sequence detection unwraps <code class="docutils literal notranslate"><span class="pre">Optional</span></code>/<code class="docutils literal notranslate"><span class="pre">Union</span></code> annotations.</p></li>
|
||
<li><p>An <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> <code class="docutils literal notranslate"><span class="pre">problem_handler</span></code> is now applied on every error path — the
|
||
negotiated 404/500 path, route-level 422/504/405 responses, and
|
||
<code class="docutils literal notranslate"><span class="pre">resp.problem()</span></code> — instead of being silently dropped with a logged warning
|
||
and a never-awaited coroutine.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">SecurityHeadersMiddleware</span></code> no longer crashes every response when a header
|
||
value is <code class="docutils literal notranslate"><span class="pre">None</span></code> — a <code class="docutils literal notranslate"><span class="pre">None</span></code> value in <code class="docutils literal notranslate"><span class="pre">headers=</span></code> now removes that default
|
||
header (e.g. <code class="docutils literal notranslate"><span class="pre">headers={"x-frame-options":</span> <span class="pre">None}</span></code> for embeddable apps).</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">responder</span> <span class="pre">run</span> <span class="pre">app.py</span></code> registers the loaded module in <code class="docutils literal notranslate"><span class="pre">sys.modules</span></code> before
|
||
executing it, so dataclasses, pickling, and <code class="docutils literal notranslate"><span class="pre">typing.get_type_hints</span></code> inside
|
||
loaded apps work. A pre-existing module with the same name is never
|
||
clobbered (the target gets a unique key), and only the added entry is
|
||
removed if execution fails.</p></li>
|
||
<li><p>Multipart part bodies accumulate in a <code class="docutils literal notranslate"><span class="pre">bytearray</span></code> during parsing, avoiding
|
||
quadratic copying when the parser delivers a part in many chunks.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">ResponderServer</span></code> no longer crashes when constructed off the main thread or
|
||
when <code class="docutils literal notranslate"><span class="pre">is_running()</span></code>/<code class="docutils literal notranslate"><span class="pre">stop()</span></code> are called before <code class="docutils literal notranslate"><span class="pre">start()</span></code>. Signal handlers
|
||
are installed by <code class="docutils literal notranslate"><span class="pre">start()</span></code> (main thread only) and restored on <code class="docutils literal notranslate"><span class="pre">stop()</span></code>,
|
||
correctly even when multiple servers are stopped out of order.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API.path_matches_route</span></code> accepts the plain path string its docstring
|
||
documents — for HTTP and WebSocket routes — instead of raising <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>;
|
||
ASGI scope mappings are still accepted.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API.session(base_url=...)</span></code> rebuilds the cached test client when called
|
||
with a different <code class="docutils literal notranslate"><span class="pre">base_url</span></code> instead of silently returning the previous
|
||
client bound to the old address.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v8-0-0-2026-07-01">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.3.0..v8.0.0">v8.0.0</a> - 2026-07-01<a class="headerlink" href="#v8-0-0-2026-07-01" title="Link to this heading">¶</a></h2>
|
||
<section id="id20">
|
||
<h3>Added<a class="headerlink" href="#id20" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Standalone router composition: <code class="docutils literal notranslate"><span class="pre">responder.Router</span></code> records route declarations
|
||
without an <code class="docutils literal notranslate"><span class="pre">API</span></code> instance — like Flask blueprints or FastAPI’s <code class="docutils literal notranslate"><span class="pre">APIRouter</span></code> —
|
||
and <code class="docutils literal notranslate"><span class="pre">api.include_router(router,</span> <span class="pre">prefix=...)</span></code> attaches them. Routers nest
|
||
(prefixes compose, tags merge, dependencies concatenate), carry group-level
|
||
<code class="docutils literal notranslate"><span class="pre">tags</span></code>/<code class="docutils literal notranslate"><span class="pre">dependencies</span></code>/<code class="docutils literal notranslate"><span class="pre">auth</span></code> defaults that individual routes may override,
|
||
scope their <code class="docutils literal notranslate"><span class="pre">before_request</span></code> hooks to the mounted prefix, and can be included
|
||
at more than one prefix. Declarations are replayed through <code class="docutils literal notranslate"><span class="pre">api.route()</span></code>, so
|
||
auth inheritance, <code class="docutils literal notranslate"><span class="pre">Depends</span></code> guards, and OpenAPI metadata work exactly as if
|
||
declared on the API directly. Including a view with auth/tags/dependencies
|
||
that conflict with an earlier registration of the same function raises
|
||
<code class="docutils literal notranslate"><span class="pre">ValueError</span></code> instead of silently rewriting the earlier route (an
|
||
access-control hazard otherwise). <code class="docutils literal notranslate"><span class="pre">api.group()</span></code> remains for quick same-file
|
||
prefix grouping.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id21">
|
||
<h3>Changed<a class="headerlink" href="#id21" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Text responses now declare their charset the standard way —
|
||
<code class="docutils literal notranslate"><span class="pre">Content-Type:</span> <span class="pre">text/...;</span> <span class="pre">charset=<encoding></span></code> — and <code class="docutils literal notranslate"><span class="pre">resp.encoding</span></code> is honored
|
||
when encoding <code class="docutils literal notranslate"><span class="pre">str</span></code> bodies for all text types (previously <code class="docutils literal notranslate"><span class="pre">resp.html</span></code> ignored
|
||
it and str bodies fell through to a UTF-8 encode, producing mojibake for e.g.
|
||
<code class="docutils literal notranslate"><span class="pre">latin-1</span></code>). The charset parameter is only added when the framework actually
|
||
encodes a <code class="docutils literal notranslate"><span class="pre">str</span></code> body; raw <code class="docutils literal notranslate"><span class="pre">bytes</span></code> bodies (e.g. <code class="docutils literal notranslate"><span class="pre">resp.file()</span></code>) keep their bare
|
||
media type. The nonstandard <code class="docutils literal notranslate"><span class="pre">Encoding</span></code> response header is no longer sent.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.redirect()</span></code> (and the <code class="docutils literal notranslate"><span class="pre">api.redirect()</span></code> helper) now default to a
|
||
method-preserving <code class="docutils literal notranslate"><span class="pre">307</span> <span class="pre">Temporary</span> <span class="pre">Redirect</span></code> instead of <code class="docutils literal notranslate"><span class="pre">301</span> <span class="pre">Moved</span> <span class="pre">Permanently</span></code>,
|
||
which browsers cache indefinitely and legacy clients rewrite POST→GET. Pass
|
||
<code class="docutils literal notranslate"><span class="pre">permanent=True</span></code> for a <code class="docutils literal notranslate"><span class="pre">308</span> <span class="pre">Permanent</span> <span class="pre">Redirect</span></code>; an explicit <code class="docutils literal notranslate"><span class="pre">status_code=</span></code>
|
||
still takes precedence.</p></li>
|
||
<li><p>YAML responses are served as <code class="docutils literal notranslate"><span class="pre">application/yaml</span></code> (the RFC 9512 registered
|
||
media type) instead of the legacy <code class="docutils literal notranslate"><span class="pre">application/x-yaml</span></code>; the OpenAPI
|
||
<code class="docutils literal notranslate"><span class="pre">/schema.yml</span></code> route follows suit. Inbound requests are unaffected — bodies
|
||
sent with either media type still parse as YAML, and
|
||
<code class="docutils literal notranslate"><span class="pre">Accept:</span> <span class="pre">application/x-yaml</span></code> still negotiates a YAML response.</p></li>
|
||
<li><p>An empty or whitespace-only YAML request body now raises <code class="docutils literal notranslate"><span class="pre">400</span> <span class="pre">Bad</span> <span class="pre">Request</span></code>
|
||
from <code class="docutils literal notranslate"><span class="pre">req.media()</span></code>, matching the JSON format (previously <code class="docutils literal notranslate"><span class="pre">yaml.safe_load</span></code>
|
||
silently returned <code class="docutils literal notranslate"><span class="pre">None</span></code>). An explicit YAML <code class="docutils literal notranslate"><span class="pre">null</span></code> document still parses to
|
||
<code class="docutils literal notranslate"><span class="pre">None</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">url_for</span></code> now raises <code class="docutils literal notranslate"><span class="pre">RouteNotFoundError</span></code> (a <code class="docutils literal notranslate"><span class="pre">LookupError</span></code> subclass,
|
||
importable as <code class="docutils literal notranslate"><span class="pre">responder.RouteNotFoundError</span></code>) for an unknown endpoint or
|
||
route name instead of returning <code class="docutils literal notranslate"><span class="pre">None</span></code> (which rendered a literal “None” in
|
||
templates), and generated URLs percent-encode parameter values —
|
||
<code class="docutils literal notranslate"><span class="pre">url_for(view,</span> <span class="pre">name="a</span> <span class="pre">b")</span></code> yields <code class="docutils literal notranslate"><span class="pre">/file/a%20b</span></code>; <code class="docutils literal notranslate"><span class="pre">{param:path}</span></code> segments
|
||
keep their slashes.</p></li>
|
||
<li><p>Requests into a WSGI mount no longer build a fresh <code class="docutils literal notranslate"><span class="pre">a2wsgi.WSGIMiddleware</span></code>
|
||
(and its per-instance <code class="docutils literal notranslate"><span class="pre">ThreadPoolExecutor</span></code>) on every request; the app is
|
||
wrapped once, at mount time.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API()</span></code> no longer creates <code class="docutils literal notranslate"><span class="pre">static_dir</span></code> implicitly. Merely instantiating
|
||
<code class="docutils literal notranslate"><span class="pre">API()</span></code> used to <code class="docutils literal notranslate"><span class="pre">mkdir</span></code> an empty <code class="docutils literal notranslate"><span class="pre">static/</span></code> into the working directory (and
|
||
failed on read-only filesystems); the default <code class="docutils literal notranslate"><span class="pre">static/</span></code> is now mounted only
|
||
when the directory already exists, and an explicitly passed <code class="docutils literal notranslate"><span class="pre">static_dir</span></code> that
|
||
doesn’t exist raises <code class="docutils literal notranslate"><span class="pre">FileNotFoundError</span></code> at construction. <code class="docutils literal notranslate"><span class="pre">static_dir=None</span></code>
|
||
still disables static serving, and the docstrings no longer claim
|
||
<code class="docutils literal notranslate"><span class="pre">static_dir</span></code>/<code class="docutils literal notranslate"><span class="pre">templates_dir</span></code> are “created for you”.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id22">
|
||
<h3>Fixed<a class="headerlink" href="#id22" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">Request.cookies</span></code> no longer silently drops cookies: the <code class="docutils literal notranslate"><span class="pre">Cookie</span></code> header is
|
||
now parsed with Starlette’s tolerant parser instead of
|
||
<code class="docutils literal notranslate"><span class="pre">http.cookies.SimpleCookie</span></code>, which aborted at the first nonconforming token
|
||
(e.g. <code class="docutils literal notranslate"><span class="pre">b[]=2</span></code>) and discarded that cookie and every one after it.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">Response.headers</span></code> is now a case-insensitive, case-preserving mapping, so a
|
||
handler setting <code class="docutils literal notranslate"><span class="pre">resp.headers['content-type']</span></code> replaces the framework’s
|
||
<code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> instead of emitting both headers on the wire (and
|
||
<code class="docutils literal notranslate"><span class="pre">no_content()</span></code> no longer needs to pop both spellings). <code class="docutils literal notranslate"><span class="pre">CaseInsensitiveDict</span></code>
|
||
construction from a mapping, <code class="docutils literal notranslate"><span class="pre">|=</span></code>/<code class="docutils literal notranslate"><span class="pre">|</span></code>, <code class="docutils literal notranslate"><span class="pre">.copy()</span></code>, and <code class="docutils literal notranslate"><span class="pre">.fromkeys()</span></code> are also
|
||
case-insensitive now — each previously bypassed the lowercasing — iteration
|
||
preserves the casing keys were set with, and instances survive <code class="docutils literal notranslate"><span class="pre">pickle</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">copy.copy</span></code>, and <code class="docutils literal notranslate"><span class="pre">copy.deepcopy</span></code> round-trips.</p></li>
|
||
<li><p>Background tasks now support async functions: <code class="docutils literal notranslate"><span class="pre">@api.background.task</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">api.background.run</span></code> drive an <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> to completion via <code class="docutils literal notranslate"><span class="pre">asyncio.run</span></code> on
|
||
the worker thread (a <code class="docutils literal notranslate"><span class="pre">functools.partial</span></code> wrapping one works too). Previously
|
||
an async task silently produced a never-awaited coroutine and the job never
|
||
ran. Background worker threads are also now named <code class="docutils literal notranslate"><span class="pre">responder-background-*</span></code>
|
||
for easier debugging. Sync task behavior is unchanged.</p></li>
|
||
<li><p>Assigning <code class="docutils literal notranslate"><span class="pre">templates.context</span> <span class="pre">=</span> <span class="pre">{...}</span></code> no longer wipes Jinja2’s built-in
|
||
globals (<code class="docutils literal notranslate"><span class="pre">range</span></code>, <code class="docutils literal notranslate"><span class="pre">namespace</span></code>, <code class="docutils literal notranslate"><span class="pre">cycler</span></code>, <code class="docutils literal notranslate"><span class="pre">joiner</span></code>, <code class="docutils literal notranslate"><span class="pre">lipsum</span></code>, <code class="docutils literal notranslate"><span class="pre">dict</span></code>) —
|
||
previously any template using <code class="docutils literal notranslate"><span class="pre">range()</span></code> after a context assignment raised
|
||
<code class="docutils literal notranslate"><span class="pre">UndefinedError</span></code>. The setter now updates the globals dict in place (keeping
|
||
the sync and async environments sharing one globals object), and reassigning
|
||
the context restores any built-in a previous assignment had shadowed.</p></li>
|
||
<li><p>The GraphQL view now executes queries with <code class="docutils literal notranslate"><span class="pre">schema.execute_async</span></code>, so
|
||
<code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> resolvers (first-class in graphene 3) resolve correctly instead
|
||
of failing with a “coroutine was never awaited” error, and resolvers can
|
||
yield the event loop while they await. The query document is also parsed once
|
||
and shared by the GET-mutation guard and introspection/depth validation
|
||
instead of being re-parsed by each.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API(lifespan=...)</span></code> no longer silently disables <code class="docutils literal notranslate"><span class="pre">on_event</span></code> handlers: startup
|
||
events run after the lifespan context manager is entered and shutdown events
|
||
before it exits, so background-task draining (registered as a shutdown event)
|
||
is no longer skipped. A raising lifespan <code class="docutils literal notranslate"><span class="pre">__aexit__</span></code> now still tears down
|
||
app-scoped dependencies and reports <code class="docutils literal notranslate"><span class="pre">lifespan.shutdown.failed</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">add_route(default=True)</span></code> with a Responder <code class="docutils literal notranslate"><span class="pre">(req,</span> <span class="pre">resp)</span></code> view no longer
|
||
crashes every unmatched request (the default endpoint was invoked ASGI-style,
|
||
raising <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> → 500). A view-style default is now dispatched through
|
||
normal route semantics — before/after hooks, dependency injection, and
|
||
response handling — with empty path params; ASGI-style defaults (including
|
||
the built-in 404) are unchanged.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">HEAD</span></code> requests to a class-based view that defines only <code class="docutils literal notranslate"><span class="pre">on_get</span></code> now fall
|
||
back to <code class="docutils literal notranslate"><span class="pre">on_get</span></code> (with the response body stripped) instead of returning 405,
|
||
matching the implicit HEAD support function views already had.</p></li>
|
||
<li><p>A mount prefix with a trailing slash (<code class="docutils literal notranslate"><span class="pre">api.mount("/admin/",</span> <span class="pre">app)</span></code>) now
|
||
matches subpaths; the prefix is normalized at mount time, and the
|
||
empty-prefix root mount still catches everything.</p></li>
|
||
<li><p>An unhandled exception in a WebSocket handler now closes the socket with code
|
||
1011 (internal error) before re-raising, so clients can tell a server bug
|
||
from a network drop instead of seeing an abnormal 1006 with no close frame.</p></li>
|
||
<li><p>Two distinct dependency providers that share a <code class="docutils literal notranslate"><span class="pre">__name__</span></code> (two functions both
|
||
named <code class="docutils literal notranslate"><span class="pre">get_db</span></code>, or nested inline lambda <code class="docutils literal notranslate"><span class="pre">Depends</span></code>) no longer trip a false
|
||
<code class="docutils literal notranslate"><span class="pre">DependencyCycleError</span></code> — cycle detection now tracks provider identity,
|
||
keeping names only for the error message.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">url_for</span></code> no longer raises <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code> when any registered route uses a
|
||
callable-instance endpoint without a <code class="docutils literal notranslate"><span class="pre">__name__</span></code> (e.g. a mounted
|
||
<code class="docutils literal notranslate"><span class="pre">GraphQLView</span></code>); the by-name fallback scan now skips such endpoints.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">api.group(...).route(None)</span></code> now raises the usual “a route path is required”
|
||
error instead of silently registering a literal <code class="docutils literal notranslate"><span class="pre">/prefixNone</span></code> path built from
|
||
the f-string.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">jinja2</span></code>, <code class="docutils literal notranslate"><span class="pre">pyyaml</span></code>, and <code class="docutils literal notranslate"><span class="pre">itsdangerous</span></code> are now declared as direct
|
||
dependencies. Responder imports them directly (templates, YAML content
|
||
negotiation, and cookie-based session middleware) but previously received
|
||
them only transitively via the <code class="docutils literal notranslate"><span class="pre">starlette[full]</span></code> extra. <code class="docutils literal notranslate"><span class="pre">python-multipart</span></code>
|
||
now carries a <code class="docutils literal notranslate"><span class="pre">>=0.0.12</span></code> floor (the first release that ships the
|
||
<code class="docutils literal notranslate"><span class="pre">python_multipart</span></code> module name Responder imports), the <code class="docutils literal notranslate"><span class="pre">apispec</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">marshmallow</span></code> floors were raised to <code class="docutils literal notranslate"><span class="pre">>=6.6</span></code> and <code class="docutils literal notranslate"><span class="pre">>=3.20</span></code> to match what the
|
||
OpenAPI extension is tested against, and the build system now requires
|
||
<code class="docutils literal notranslate"><span class="pre">setuptools>=77</span></code>, the first version that supports the PEP 639 SPDX
|
||
<code class="docutils literal notranslate"><span class="pre">license</span> <span class="pre">=</span> <span class="pre">"Apache-2.0"</span></code> expression (the previous <code class="docutils literal notranslate"><span class="pre">>=42</span></code> pin could not build
|
||
the project).</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id23">
|
||
<h3>Security<a class="headerlink" href="#id23" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.download()</span></code> sanitizes user-derived filenames in <code class="docutils literal notranslate"><span class="pre">Content-Disposition</span></code>:
|
||
CR, LF, and NUL are stripped (they allowed header injection), <code class="docutils literal notranslate"><span class="pre">"</span></code> and <code class="docutils literal notranslate"><span class="pre">\</span></code> are
|
||
backslash-escaped in the quoted-string (a quote could break out of
|
||
<code class="docutils literal notranslate"><span class="pre">filename="..."</span></code>), and names containing characters outside the HTTP token set
|
||
now also carry the RFC 5987 <code class="docutils literal notranslate"><span class="pre">filename*=</span></code> form (non-ASCII names keep the
|
||
<code class="docutils literal notranslate"><span class="pre">filename*=</span></code>-only form).</p></li>
|
||
<li><p>The in-memory <code class="docutils literal notranslate"><span class="pre">MemorySessionBackend</span></code> now bounds its store (LRU eviction,
|
||
<code class="docutils literal notranslate"><span class="pre">max_keys</span></code>, default 100,000) and opportunistically sweeps expired entries on
|
||
writes, so an attacker rotating session cookies — or plain abandoned
|
||
sessions, previously deleted only on a <code class="docutils literal notranslate"><span class="pre">get()</span></code> with that exact ID — can no
|
||
longer grow process memory without bound. Eviction removes earliest-expiry
|
||
entries first, and operations are lock-guarded, as they run on threadpool
|
||
workers.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-3-0-2026-07-01">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.2.1..v7.3.0">v7.3.0</a> - 2026-07-01<a class="headerlink" href="#v7-3-0-2026-07-01" title="Link to this heading">¶</a></h2>
|
||
<section id="id24">
|
||
<h3>Added<a class="headerlink" href="#id24" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Inline <code class="docutils literal notranslate"><span class="pre">Depends(...)</span></code> can now nest inside a provider (sub-dependency chains),
|
||
matching FastAPI. Previously only named <code class="docutils literal notranslate"><span class="pre">@api.dependency()</span></code> providers could
|
||
chain; a provider with an inline <code class="docutils literal notranslate"><span class="pre">Depends</span></code> parameter raised
|
||
<code class="docutils literal notranslate"><span class="pre">DependencyResolutionError</span></code>.</p></li>
|
||
<li><p>A developer <code class="docutils literal notranslate"><span class="pre">Makefile</span></code>: bare <code class="docutils literal notranslate"><span class="pre">make</span></code> lists tasks (<code class="docutils literal notranslate"><span class="pre">test</span></code>, <code class="docutils literal notranslate"><span class="pre">lint</span></code>, <code class="docutils literal notranslate"><span class="pre">types</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">docs</span></code>, <code class="docutils literal notranslate"><span class="pre">build</span></code>, <code class="docutils literal notranslate"><span class="pre">check</span></code>, …), all run through <code class="docutils literal notranslate"><span class="pre">uv</span></code>. <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">test</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">docs</span></code> depend on <code class="docutils literal notranslate"><span class="pre">make</span> <span class="pre">uv-sync</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id25">
|
||
<h3>Changed<a class="headerlink" href="#id25" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">Request.accepts()</span></code> now honors <code class="docutils literal notranslate"><span class="pre">Accept</span></code> media ranges (<code class="docutils literal notranslate"><span class="pre">*/*</span></code>, <code class="docutils literal notranslate"><span class="pre">type/*</span></code>) and
|
||
q-values (a <code class="docutils literal notranslate"><span class="pre">q=0</span></code> range is not acceptable) instead of substring-matching the
|
||
raw header. An absent <code class="docutils literal notranslate"><span class="pre">Accept</span></code> accepts anything.</p></li>
|
||
<li><p>Request body decoding honors the standard <code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> <code class="docutils literal notranslate"><span class="pre">charset=</span></code> parameter,
|
||
using chardet only when no charset is declared.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">Request.media()</span></code> auto-detects MessagePack (<code class="docutils literal notranslate"><span class="pre">application/x-msgpack</span></code>) bodies.</p></li>
|
||
<li><p>Dependency and request-body-model signature inspection is now memoized on the
|
||
per-request path, and large <code class="docutils literal notranslate"><span class="pre">auto_etag</span></code> response bodies are hashed off the
|
||
event loop.</p></li>
|
||
<li><p>The project <code class="docutils literal notranslate"><span class="pre">Homepage</span></code> URL now points at the documentation site.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id26">
|
||
<h3>Fixed<a class="headerlink" href="#id26" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Multipart form parsing no longer emits file parts (or their filenames) as
|
||
phantom form fields, and correctly parses unquoted field names — it now uses a
|
||
real Content-Disposition parser.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">enable_logging</span></code> no longer drops a request whose <code class="docutils literal notranslate"><span class="pre">X-Request-ID</span></code> is not valid
|
||
UTF-8; the header is decoded as latin-1, matching <code class="docutils literal notranslate"><span class="pre">RequestIDMiddleware</span></code>.</p></li>
|
||
<li><p>The <code class="docutils literal notranslate"><span class="pre">responder.ext.query</span></code> descending sort keeps <code class="docutils literal notranslate"><span class="pre">None</span></code> values last, per its
|
||
documented contract (it previously pushed them to the front).</p></li>
|
||
<li><p>Mounted sub-app WSGI-vs-ASGI detection is decided from the call signature
|
||
rather than the text of a raised <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>, so a genuine <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> inside a
|
||
mounted ASGI app keeps its real traceback instead of being misclassified.</p></li>
|
||
<li><p>A user <code class="docutils literal notranslate"><span class="pre">lifespan(app)</span></code> context manager now receives the <code class="docutils literal notranslate"><span class="pre">API</span></code> instance instead
|
||
of <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">MetricsCollector</span></code> reads/writes are lock-guarded, so a concurrent <code class="docutils literal notranslate"><span class="pre">/metrics</span></code>
|
||
scrape no longer risks <code class="docutils literal notranslate"><span class="pre">RuntimeError:</span> <span class="pre">dictionary</span> <span class="pre">changed</span> <span class="pre">size</span> <span class="pre">during</span> <span class="pre">iteration</span></code> and counts stay exact on free-threaded CPython.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">Templates.render_async</span></code> uses a dedicated always-async Jinja environment
|
||
instead of toggling <code class="docutils literal notranslate"><span class="pre">is_async</span></code> on a shared one, fixing a race between
|
||
concurrent sync and async renders.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id27">
|
||
<h3>Security<a class="headerlink" href="#id27" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>The in-memory rate-limit <code class="docutils literal notranslate"><span class="pre">MemoryBackend</span></code> now bounds its key set (LRU eviction,
|
||
<code class="docutils literal notranslate"><span class="pre">max_keys</span></code>), so a client rotating source IPs (or spoofing <code class="docutils literal notranslate"><span class="pre">X-Forwarded-For</span></code>)
|
||
can no longer grow process memory without bound.</p></li>
|
||
<li><p>The Server-Sent Events heartbeat queue is now bounded, restoring producer
|
||
backpressure so a slow/stalled client can’t make it buffer without limit.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-2-1-2026-07-01">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.2.0..v7.2.1">v7.2.1</a> - 2026-07-01<a class="headerlink" href="#v7-2-1-2026-07-01" title="Link to this heading">¶</a></h2>
|
||
<section id="id28">
|
||
<h3>Security<a class="headerlink" href="#id28" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>The GraphQL view now rejects mutations sent over HTTP <code class="docutils literal notranslate"><span class="pre">GET</span></code> (returns <code class="docutils literal notranslate"><span class="pre">405</span></code>
|
||
with <code class="docutils literal notranslate"><span class="pre">Allow:</span> <span class="pre">POST</span></code>). <code class="docutils literal notranslate"><span class="pre">GET</span></code> must be safe/idempotent; running a mutation via
|
||
<code class="docutils literal notranslate"><span class="pre">GET</span> <span class="pre">/graphql?query=mutation{...}</span></code> made it CSRF-able (a plain <code class="docutils literal notranslate"><span class="pre"><img</span> <span class="pre">src></span></code>
|
||
would trigger it with the victim’s cookies) and cacheable. Query operations
|
||
over <code class="docutils literal notranslate"><span class="pre">GET</span></code> are unaffected.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id29">
|
||
<h3>Fixed<a class="headerlink" href="#id29" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>The client generator now escapes path-parameter names when interpolating them
|
||
into generated string literals (Python <code class="docutils literal notranslate"><span class="pre">repr</span></code>, JS via the JS escaper, Ruby via
|
||
a new single-quoted escaper). A name containing a quote or backslash in an
|
||
(untrusted) OpenAPI spec previously produced a client that failed to parse.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-2-0-2026-07-01">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.1.3..v7.2.0">v7.2.0</a> - 2026-07-01<a class="headerlink" href="#v7-2-0-2026-07-01" title="Link to this heading">¶</a></h2>
|
||
<section id="id30">
|
||
<h3>Security<a class="headerlink" href="#id30" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Server-Sent Events frames can no longer be spoofed via caller-supplied field
|
||
values. A <code class="docutils literal notranslate"><span class="pre">\r</span></code> or <code class="docutils literal notranslate"><span class="pre">\n</span></code> in an SSE <code class="docutils literal notranslate"><span class="pre">event</span></code>, <code class="docutils literal notranslate"><span class="pre">id</span></code>, <code class="docutils literal notranslate"><span class="pre">retry</span></code>, or comment field is
|
||
now stripped (these are single-line fields; a line break would terminate the
|
||
field and inject additional SSE lines/frames), and <code class="docutils literal notranslate"><span class="pre">data</span></code> splits on any line
|
||
terminator (<code class="docutils literal notranslate"><span class="pre">\r\n</span></code>, <code class="docutils literal notranslate"><span class="pre">\r</span></code>, <code class="docutils literal notranslate"><span class="pre">\n</span></code>) so a lone <code class="docutils literal notranslate"><span class="pre">\r</span></code> can’t inject a new field.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id31">
|
||
<h3>Added<a class="headerlink" href="#id31" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API(ws_idle_timeout=...)</span></code> closes a WebSocket that waits too long for the next
|
||
inbound message (close code <code class="docutils literal notranslate"><span class="pre">1001</span></code>). The deadline resets on every message, so
|
||
it bounds idle time between messages, not total connection lifetime. Defaults
|
||
to <code class="docutils literal notranslate"><span class="pre">None</span></code> (unlimited), preserving existing behavior.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id32">
|
||
<h3>Changed<a class="headerlink" href="#id32" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Tightened the mypy configuration: <code class="docutils literal notranslate"><span class="pre">no_implicit_optional</span></code>, <code class="docutils literal notranslate"><span class="pre">warn_unused_ignores</span></code>,
|
||
and <code class="docutils literal notranslate"><span class="pre">warn_redundant_casts</span></code> are now on. Removed the blanket
|
||
<code class="docutils literal notranslate"><span class="pre">implicit_optional</span> <span class="pre">=</span> <span class="pre">true</span></code>. Cleaned up the stale <code class="docutils literal notranslate"><span class="pre">#</span> <span class="pre">type:</span> <span class="pre">ignore</span></code> comments this
|
||
surfaced.</p></li>
|
||
<li><p>Completed type annotations across the codebase and enabled mypy
|
||
<code class="docutils literal notranslate"><span class="pre">disallow_incomplete_defs</span></code>, so partially-annotated functions now fail type
|
||
checking. Annotations only — no runtime behavior changed.</p></li>
|
||
<li><p>Dropped the separate “Generated client syntax checks” CI job.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id33">
|
||
<h3>Fixed<a class="headerlink" href="#id33" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Synchronous lifecycle handlers (<code class="docutils literal notranslate"><span class="pre">startup</span></code>/<code class="docutils literal notranslate"><span class="pre">shutdown</span></code> events) and synchronous
|
||
exception handlers now run in a thread pool instead of directly on the event
|
||
loop, so a blocking call in one no longer stalls the server.</p></li>
|
||
<li><p>Content-Type matching is now case-insensitive, per RFC 7231. Requests sent
|
||
with e.g. <code class="docutils literal notranslate"><span class="pre">Application/JSON</span></code> or <code class="docutils literal notranslate"><span class="pre">Multipart/Form-Data</span></code> are negotiated and
|
||
parsed correctly instead of falling through to the wrong parser. Affects
|
||
<code class="docutils literal notranslate"><span class="pre">Request.is_json</span></code>, <code class="docutils literal notranslate"><span class="pre">Request.media()</span></code> format auto-detection, and multipart
|
||
form parsing (including an uppercased <code class="docutils literal notranslate"><span class="pre">Boundary</span></code> parameter name).</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">ResponderServer.__init__</span></code>’s <code class="docutils literal notranslate"><span class="pre">limit_max_requests</span></code> parameter was annotated
|
||
<code class="docutils literal notranslate"><span class="pre">int</span></code> but defaulted to <code class="docutils literal notranslate"><span class="pre">None</span></code>; it is now <code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">|</span> <span class="pre">None</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-1-3-2026-07-01">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.1.2..v7.1.3">v7.1.3</a> - 2026-07-01<a class="headerlink" href="#v7-1-3-2026-07-01" title="Link to this heading">¶</a></h2>
|
||
<section id="id34">
|
||
<h3>Fixed<a class="headerlink" href="#id34" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">RedisBackend</span></code>/<code class="docutils literal notranslate"><span class="pre">AsyncRedisBackend</span></code> rate limiters now increment the counter
|
||
and set its expiry in a single atomic server-side step (Lua <code class="docutils literal notranslate"><span class="pre">EVAL</span></code>). The
|
||
previous separate <code class="docutils literal notranslate"><span class="pre">INCR</span></code> + <code class="docutils literal notranslate"><span class="pre">EXPIRE</span></code> calls could leave a key without a TTL if
|
||
the process died between them, locking that client out until manual eviction.</p></li>
|
||
<li><p>Background tasks submitted via <code class="docutils literal notranslate"><span class="pre">api.background</span></code> are now drained on application
|
||
shutdown instead of being abandoned, via a registered shutdown handler that
|
||
calls <code class="docutils literal notranslate"><span class="pre">BackgroundQueue.shutdown()</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id35">
|
||
<h3>Changed<a class="headerlink" href="#id35" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>CI now runs <code class="docutils literal notranslate"><span class="pre">ruff</span> <span class="pre">check</span></code> and <code class="docutils literal notranslate"><span class="pre">mypy</span></code> on every push and pull request (new
|
||
<code class="docutils literal notranslate"><span class="pre">Lint</span> <span class="pre">&</span> <span class="pre">Types</span></code> workflow), not just during the manual release guard.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-1-2-2026-06-30">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.1.1..v7.1.2">v7.1.2</a> - 2026-06-30<a class="headerlink" href="#v7-1-2-2026-06-30" title="Link to this heading">¶</a></h2>
|
||
<section id="id36">
|
||
<h3>Added<a class="headerlink" href="#id36" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>New example apps: <code class="docutils literal notranslate"><span class="pre">examples/todo.py</span></code>, <code class="docutils literal notranslate"><span class="pre">examples/fortunes.py</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">examples/shortlinks.py</span></code>, <code class="docutils literal notranslate"><span class="pre">examples/tarot.py</span></code>, and <code class="docutils literal notranslate"><span class="pre">examples/webhooks.py</span></code>.</p></li>
|
||
<li><p>Modernized <code class="docutils literal notranslate"><span class="pre">examples/helloworld.py</span></code>, <code class="docutils literal notranslate"><span class="pre">lifespan.py</span></code>, <code class="docutils literal notranslate"><span class="pre">marimo_mount.py</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">rest_api.py</span></code>, <code class="docutils literal notranslate"><span class="pre">sse_stream.py</span></code>, <code class="docutils literal notranslate"><span class="pre">user.py</span></code>, and <code class="docutils literal notranslate"><span class="pre">websocket_chat.py</span></code>, with
|
||
matching coverage in <code class="docutils literal notranslate"><span class="pre">tests/test_examples.py</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id37">
|
||
<h3>Fixed<a class="headerlink" href="#id37" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">RateLimiter</span></code> and <code class="docutils literal notranslate"><span class="pre">enable_logging</span></code>’s <code class="docutils literal notranslate"><span class="pre">LoggingMiddleware</span></code> keyed/recorded the
|
||
client IP from the TCP peer only, which behind any reverse proxy is the
|
||
proxy itself — every visitor shared one rate-limit bucket and access logs
|
||
showed the proxy’s address for every request. Both now accept
|
||
<code class="docutils literal notranslate"><span class="pre">trust_proxy_headers=True</span></code> to read the real client from
|
||
<code class="docutils literal notranslate"><span class="pre">X-Forwarded-For</span></code>/<code class="docutils literal notranslate"><span class="pre">X-Real-IP</span></code> instead (opt-in, since trusting those headers
|
||
without a proxy in front lets a client spoof its own address).</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-1-1-2026-06-30">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.1.0..v7.1.1">v7.1.1</a> - 2026-06-30<a class="headerlink" href="#v7-1-1-2026-06-30" title="Link to this heading">¶</a></h2>
|
||
<section id="id38">
|
||
<h3>Added<a class="headerlink" href="#id38" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">examples/atelier.py</span></code> is now the canonical showcase app and contract fixture
|
||
for auth policies, OpenAPI metadata, response helpers, problem details, and
|
||
generated clients.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id39">
|
||
<h3>Fixed<a class="headerlink" href="#id39" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Auth-injected <code class="docutils literal notranslate"><span class="pre">user</span></code>, <code class="docutils literal notranslate"><span class="pre">principal</span></code>, and <code class="docutils literal notranslate"><span class="pre">auth</span></code> parameters are no longer treated
|
||
as request-body Pydantic models on routes with JSON bodies.</p></li>
|
||
<li><p>Generated clients now keep scanning success responses until they find a JSON
|
||
schema, instead of giving up when an earlier 2xx response has no body.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-1-0-2026-06-30">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.0.5..v7.1.0">v7.1.0</a> - 2026-06-30<a class="headerlink" href="#v7-1-0-2026-06-30" title="Link to this heading">¶</a></h2>
|
||
<section id="id40">
|
||
<h3>Added<a class="headerlink" href="#id40" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">api.policy(name,</span> <span class="pre">auth)</span></code> creates named, reusable auth policy wrappers without
|
||
changing the wrapped auth scheme’s runtime or OpenAPI behavior.</p></li>
|
||
<li><p>Route decorators now accept <code class="docutils literal notranslate"><span class="pre">responses=</span></code>, <code class="docutils literal notranslate"><span class="pre">examples=</span></code>, <code class="docutils literal notranslate"><span class="pre">response_examples=</span></code>,
|
||
and <code class="docutils literal notranslate"><span class="pre">openapi_extra=</span></code> for nearby OpenAPI operation authoring that deep-merges
|
||
with generated schemas and framework error responses.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.created(...)</span></code>, <code class="docutils literal notranslate"><span class="pre">resp.no_content()</span></code>, and <code class="docutils literal notranslate"><span class="pre">resp.problem(...)</span></code> provide
|
||
focused helpers for common REST responses and manual problem-details payloads.</p></li>
|
||
<li><p>A canonical contract fixture now validates a representative OpenAPI document
|
||
and generated Python client against the same in-process app.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">scripts/release.py</span></code> orchestrates the release guard, tagging, GitHub release
|
||
creation, package build, and Twine upload with a dry-run default.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-0-5-2026-06-30">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.0.4..v7.0.5">v7.0.5</a> - 2026-06-30<a class="headerlink" href="#v7-0-5-2026-06-30" title="Link to this heading">¶</a></h2>
|
||
<section id="id41">
|
||
<h3>Added<a class="headerlink" href="#id41" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Generated OpenAPI documents are now validated in tests for both OpenAPI 3.0.x
|
||
and 3.1.x, including problem-details and legacy-error modes.</p></li>
|
||
<li><p>A <code class="docutils literal notranslate"><span class="pre">scripts/release_check.py</span></code> guard verifies release metadata, optional clean
|
||
tree and tag state, tests, lint, types, docs, package builds, wheel contents,
|
||
and <code class="docutils literal notranslate"><span class="pre">twine</span> <span class="pre">check</span></code>.</p></li>
|
||
<li><p>Runtime contracts documentation now describes framework error responses, auth
|
||
inheritance, dependency lifecycle, response-model failures, and OpenAPI
|
||
defaults.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id42">
|
||
<h3>Changed<a class="headerlink" href="#id42" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Wheels now only package <code class="docutils literal notranslate"><span class="pre">responder</span></code> and its declared package data, keeping
|
||
top-level docs, examples, and tests out of the installed wheel.</p></li>
|
||
<li><p>CI now runs the release guard’s metadata, build, wheel-content, and
|
||
<code class="docutils literal notranslate"><span class="pre">twine</span> <span class="pre">check</span></code> path on every push and pull request.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id43">
|
||
<h3>Fixed<a class="headerlink" href="#id43" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>The Sphinx docs build now treats Markdown files as sources, making existing
|
||
Markdown project pages and the changelog symlink resolvable from the toctree.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-0-4-2026-06-30">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.0.3..v7.0.4">v7.0.4</a> - 2026-06-30<a class="headerlink" href="#v7-0-4-2026-06-30" title="Link to this heading">¶</a></h2>
|
||
<section id="id44">
|
||
<h3>Fixed<a class="headerlink" href="#id44" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>HEAD responses now send headers without an ASGI response body while preserving
|
||
the <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> a GET would have produced for non-streaming responses.</p></li>
|
||
<li><p>Query-string parameters with blank values (for example <code class="docutils literal notranslate"><span class="pre">?q=</span></code>) are preserved
|
||
instead of being treated as missing.</p></li>
|
||
<li><p>Mutating <code class="docutils literal notranslate"><span class="pre">req.path_params</span></code> during a request can no longer poison the route
|
||
resolution cache for later requests to the same concrete path.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-0-3-2026-06-30">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.0.2..v7.0.3">v7.0.3</a> - 2026-06-30<a class="headerlink" href="#v7-0-3-2026-06-30" title="Link to this heading">¶</a></h2>
|
||
<section id="id45">
|
||
<h3>Fixed<a class="headerlink" href="#id45" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>OpenAPI now documents legacy JSON error responses when
|
||
<code class="docutils literal notranslate"><span class="pre">API(problem_details=False)</span></code> is set, and omits the <code class="docutils literal notranslate"><span class="pre">ProblemDetails</span></code> schema in
|
||
that mode.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">auth.optional()</span></code> now rejects malformed <code class="docutils literal notranslate"><span class="pre">Authorization</span></code> headers instead of
|
||
treating them as anonymous requests.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">problem_handler</span></code> now receives the underlying exception for validation,
|
||
response-model, and after-hook failures, and a failing handler falls back to
|
||
the original framework payload.</p></li>
|
||
<li><p>Scoped auth insufficient-scope challenges now keep valid
|
||
<code class="docutils literal notranslate"><span class="pre">WWW-Authenticate</span></code> formatting when the base challenge already has parameters.</p></li>
|
||
<li><p>Dependency-resolution errors no longer duplicate the active dependency in the
|
||
reported chain.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-0-2-2026-06-30">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.0.1..v7.0.2">v7.0.2</a> - 2026-06-30<a class="headerlink" href="#v7-0-2-2026-06-30" title="Link to this heading">¶</a></h2>
|
||
<section id="id46">
|
||
<h3>Added<a class="headerlink" href="#id46" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API(problem_handler=...)</span></code> can enrich framework-generated
|
||
<code class="docutils literal notranslate"><span class="pre">application/problem+json</span></code> payloads with fields such as <code class="docutils literal notranslate"><span class="pre">type</span></code>, <code class="docutils literal notranslate"><span class="pre">instance</span></code>,
|
||
application error codes, or links.</p></li>
|
||
<li><p>Problem-details payloads include <code class="docutils literal notranslate"><span class="pre">request_id</span></code> when request ID middleware or
|
||
structured logging is enabled.</p></li>
|
||
<li><p>OpenAPI generation now registers a reusable <code class="docutils literal notranslate"><span class="pre">ProblemDetails</span></code> schema and
|
||
documents common framework error responses (<code class="docutils literal notranslate"><span class="pre">400</span></code>, <code class="docutils literal notranslate"><span class="pre">401</span></code>, <code class="docutils literal notranslate"><span class="pre">403</span></code>, <code class="docutils literal notranslate"><span class="pre">404</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">405</span></code>, <code class="docutils literal notranslate"><span class="pre">413</span></code>, <code class="docutils literal notranslate"><span class="pre">422</span></code>, <code class="docutils literal notranslate"><span class="pre">500</span></code>, and <code class="docutils literal notranslate"><span class="pre">504</span></code> when configured).</p></li>
|
||
<li><p>OpenAPI operations now receive default <code class="docutils literal notranslate"><span class="pre">operationId</span></code>, <code class="docutils literal notranslate"><span class="pre">summary</span></code>, and tags
|
||
when route metadata does not supply them.</p></li>
|
||
<li><p>Generated Python, JavaScript, TypeScript, Ruby, and PHP clients expose parsed
|
||
problem details on <code class="docutils literal notranslate"><span class="pre">APIError.problem</span></code>; Python also surfaces <code class="docutils literal notranslate"><span class="pre">title</span></code>, <code class="docutils literal notranslate"><span class="pre">detail</span></code>,
|
||
and <code class="docutils literal notranslate"><span class="pre">errors</span></code> convenience attributes.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">auth.optional()</span></code> accepts missing credentials while still rejecting invalid
|
||
credentials, injecting <code class="docutils literal notranslate"><span class="pre">None</span></code> for anonymous requests and documenting optional
|
||
security in OpenAPI.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API(trace_dispatch=True)</span></code> emits debug logs for the documented dispatch
|
||
stages: before hooks, auth, dependencies, handlers, and after hooks.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">responder.testing.assert_problem(...)</span></code> provides a small assertion helper for
|
||
problem-details responses.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id47">
|
||
<h3>Changed<a class="headerlink" href="#id47" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Scoped auth failures now include a <code class="docutils literal notranslate"><span class="pre">WWW-Authenticate</span></code> insufficient-scope
|
||
challenge when the wrapped scheme provides a challenge.</p></li>
|
||
<li><p>Dependency-resolution errors include the dependency chain being resolved.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-0-1-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v7.0.0..v7.0.1">v7.0.1</a> - 2026-06-29<a class="headerlink" href="#v7-0-1-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<section id="id48">
|
||
<h3>Fixed<a class="headerlink" href="#id48" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Problem-details responses for <code class="docutils literal notranslate"><span class="pre">413</span></code> errors now use the RFC 9110 title
|
||
<code class="docutils literal notranslate"><span class="pre">Content</span> <span class="pre">Too</span> <span class="pre">Large</span></code> consistently across Python runtimes.</p></li>
|
||
<li><p>CI now installs the checked-out package editable during tests so cached wheels
|
||
cannot mask source changes during release validation.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v7-0-0-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.6.1..v7.0.0">v7.0.0</a> - 2026-06-29<a class="headerlink" href="#v7-0-0-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A major release focused on explicit runtime contracts: problem details by
|
||
default, first-class app auth (with scope/role checks), route-level dependency
|
||
guards, and clearer optional production-server packaging. Python 3.11 is now the
|
||
minimum, and the deprecated <code class="docutils literal notranslate"><span class="pre">request_model=</span></code> route option has been removed.</p>
|
||
<section id="id49">
|
||
<h3>Added<a class="headerlink" href="#id49" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API(auth=...)</span></code> applies auth helpers to routes by default. Routes can opt out
|
||
with <code class="docutils literal notranslate"><span class="pre">auth=None</span></code>.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">ScopedAuth</span></code> and <code class="docutils literal notranslate"><span class="pre">auth.requires(...)</span></code> add lightweight scope/role checks on top
|
||
of existing auth helpers, returning <code class="docutils literal notranslate"><span class="pre">403</span></code> when the principal lacks a required
|
||
scope and documenting scoped OpenAPI security requirements.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">dependencies=[Depends(...)]</span></code> on route decorators runs dependency-graph
|
||
dependencies before the handler without injecting an unused return value.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">responder[server]</span></code> keeps Granian as an optional production ASGI dependency.
|
||
<code class="docutils literal notranslate"><span class="pre">uvicorn</span></code> remains in the default install and is still used by
|
||
<code class="docutils literal notranslate"><span class="pre">api.run()</span></code> unless <code class="docutils literal notranslate"><span class="pre">server="granian"</span></code> is requested.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">api.run(server="granian")</span></code> runs the current app with Granian’s embedded ASGI
|
||
server when <code class="docutils literal notranslate"><span class="pre">responder[server]</span></code> is installed, and raises a targeted install
|
||
error when it is missing.</p></li>
|
||
<li><p>Route dispatch ordering for before hooks, auth, dependency-guards, handler,
|
||
and after hooks is now part of the documented v7 behavior.</p></li>
|
||
<li><p>A v7 migration guide covering default error responses, auth inheritance,
|
||
route dependency guards, removed request-model compatibility, and the server
|
||
extra.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id50">
|
||
<h3>Changed<a class="headerlink" href="#id50" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Framework-generated errors now use <code class="docutils literal notranslate"><span class="pre">application/problem+json</span></code> by default.
|
||
<code class="docutils literal notranslate"><span class="pre">errors</span></code> remains an extension member when present (for example on 422s),
|
||
so migration is media-type oriented instead of response-shape oriented.
|
||
Pass <code class="docutils literal notranslate"><span class="pre">problem_details=False</span></code> to keep the legacy JSON/plain-text negotiation.</p></li>
|
||
<li><p>Problem-details responses are serialized as JSON bytes regardless of the
|
||
request’s <code class="docutils literal notranslate"><span class="pre">Accept</span></code> header, and unhandled 500s use the same problem-details
|
||
contract by default.</p></li>
|
||
<li><p>Explicit <code class="docutils literal notranslate"><span class="pre">Depends(...)</span></code> parameters and registered dependencies take
|
||
precedence over auth principal-name injection when they use the same handler
|
||
parameter name; the authenticated principal remains available on request
|
||
state.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">req.method</span></code> now returns an exact <code class="docutils literal notranslate"><span class="pre">str</span></code>; the no-op exported <code class="docutils literal notranslate"><span class="pre">HTTPMethod</span></code>
|
||
subclass has been removed.</p></li>
|
||
<li><p>Python 3.11 is now the minimum supported Python version; internal datetime
|
||
handling uses the stdlib <code class="docutils literal notranslate"><span class="pre">datetime.UTC</span></code> alias accordingly.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id51">
|
||
<h3>Removed<a class="headerlink" href="#id51" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>The deprecated <code class="docutils literal notranslate"><span class="pre">request_model=</span></code> route option and <code class="docutils literal notranslate"><span class="pre">req.state.validated</span></code>
|
||
compatibility path have been removed. Use required Pydantic-typed handler
|
||
parameters for request-body validation.</p></li>
|
||
<li><p>The deprecated private <code class="docutils literal notranslate"><span class="pre">_resolve_dependency</span></code> route helper has been removed;
|
||
the request dependency graph is resolved through the shared resolver.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id52">
|
||
<h3>Fixed<a class="headerlink" href="#id52" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Byte-range requests now cap the number of requested ranges and coalesce
|
||
overlapping or adjacent ranges before building single or multipart responses.</p></li>
|
||
<li><p>Request-scoped dependency caching now distinguishes bound methods by
|
||
instance, avoiding cross-instance value reuse.</p></li>
|
||
<li><p>WebSocket routes now resolve inline <code class="docutils literal notranslate"><span class="pre">Depends(...)</span></code> parameters and run
|
||
route-local <code class="docutils literal notranslate"><span class="pre">after=</span></code> hooks.</p></li>
|
||
<li><p>Exceptions raised by after hooks now produce a controlled 500 response using
|
||
the normal error contract.</p></li>
|
||
<li><p>OpenAPI schemas now default missing API metadata to valid string values
|
||
instead of emitting <code class="docutils literal notranslate"><span class="pre">null</span></code> for required <code class="docutils literal notranslate"><span class="pre">info</span></code> fields.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-6-1-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.6.0..v6.6.1">v6.6.1</a> - 2026-06-29<a class="headerlink" href="#v6-6-1-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A small follow-up release focused on problem-details consistency, packaging
|
||
metadata, documentation, and internal route-dispatch maintainability.</p>
|
||
<section id="id53">
|
||
<h3>Changed<a class="headerlink" href="#id53" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">problem_details=True</span></code> now also applies to production response-model
|
||
validation failures, returning <code class="docutils literal notranslate"><span class="pre">application/problem+json</span></code> for those
|
||
framework-generated <code class="docutils literal notranslate"><span class="pre">500</span></code> responses.</p></li>
|
||
<li><p>Refactored HTTP route dispatch internals into smaller helpers without changing
|
||
public behavior.</p></li>
|
||
<li><p>Updated project license metadata to the modern SPDX form used by current
|
||
packaging tools.</p></li>
|
||
<li><p>Refreshed the README with concise examples for route-local hooks, local
|
||
dependencies, route-level auth, file-upload saving, and problem-details
|
||
responses.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-6-0-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.5.3..v6.6.0">v6.6.0</a> - 2026-06-29<a class="headerlink" href="#v6-6-0-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release that adds route-local controls, explicit local
|
||
dependencies, problem-details errors, upload saving, and multipart byte ranges.</p>
|
||
<section id="id54">
|
||
<h3>Added<a class="headerlink" href="#id54" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Route-local hooks</strong> with <code class="docutils literal notranslate"><span class="pre">before=</span></code> and <code class="docutils literal notranslate"><span class="pre">after=</span></code> on <code class="docutils literal notranslate"><span class="pre">api.route()</span></code> and verb
|
||
decorators. Global hooks still run, while route-local hooks apply only to the
|
||
decorated endpoint.</p></li>
|
||
<li><p><strong>Route-level auth enforcement</strong> with <code class="docutils literal notranslate"><span class="pre">auth=</span></code>. Auth helpers such as
|
||
<code class="docutils literal notranslate"><span class="pre">BearerAuth</span></code> now enforce access, register their OpenAPI security scheme when
|
||
OpenAPI is enabled, and inject the authenticated principal into <code class="docutils literal notranslate"><span class="pre">user</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">principal</span></code>, or <code class="docutils literal notranslate"><span class="pre">auth</span></code> handler parameters.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">Depends(...)</span></code></strong> for explicit per-route dependency providers without app-wide
|
||
registration. Providers can be sync, async, generator, or async-generator
|
||
callables and can receive the current request or registered dependencies.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">problem_details=True</span></code></strong> on <code class="docutils literal notranslate"><span class="pre">API(...)</span></code> for RFC 9457-style framework errors
|
||
using <code class="docutils literal notranslate"><span class="pre">application/problem+json</span></code>.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">upload.save(path)</span></code></strong> on injected/uploaded <code class="docutils literal notranslate"><span class="pre">UploadFile</span></code> objects, with
|
||
streaming writes and optional parent-directory creation.</p></li>
|
||
<li><p><strong>Multipart byte-range responses</strong> for <code class="docutils literal notranslate"><span class="pre">resp.file()</span></code> and <code class="docutils literal notranslate"><span class="pre">resp.stream_file()</span></code>
|
||
when clients request multiple ranges.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id55">
|
||
<h3>Changed<a class="headerlink" href="#id55" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Response format encoders now respect an explicit <code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> already set on
|
||
the response instead of overwriting it during serialization.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-5-3-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.5.2..v6.5.3">v6.5.3</a> - 2026-06-29<a class="headerlink" href="#v6-5-3-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<section id="id56">
|
||
<h3>Fixed<a class="headerlink" href="#id56" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Generated <strong>TypeScript</strong> clients now type-check under <code class="docutils literal notranslate"><span class="pre">tsc</span></code> / <code class="docutils literal notranslate"><span class="pre">deno</span> <span class="pre">check</span></code>.
|
||
The opt-in <code class="docutils literal notranslate"><span class="pre">validate</span></code> helpers added in 6.5.2 emitted untyped parameters
|
||
(implicit <code class="docutils literal notranslate"><span class="pre">any</span></code>) in the shared JS/TS validation code; the TypeScript output is
|
||
now annotated. JavaScript output is unchanged.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-5-2-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.5.1..v6.5.2">v6.5.2</a> - 2026-06-29<a class="headerlink" href="#v6-5-2-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible follow-up adding opt-in generated-client validation.</p>
|
||
<section id="id57">
|
||
<h3>Added<a class="headerlink" href="#id57" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Generated Python, JavaScript, and TypeScript clients now support opt-in
|
||
runtime schema validation with <code class="docutils literal notranslate"><span class="pre">validate=True</span></code> / <code class="docutils literal notranslate"><span class="pre">validate:</span> <span class="pre">true</span></code>, raising
|
||
<code class="docutils literal notranslate"><span class="pre">APIValidationError</span></code> when outgoing JSON bodies or successful JSON responses do
|
||
not match the generated OpenAPI schemas.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-5-1-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.5.0..v6.5.1">v6.5.1</a> - 2026-06-29<a class="headerlink" href="#v6-5-1-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible follow-up that rounds out the client generator.</p>
|
||
<section id="id58">
|
||
<h3>Added<a class="headerlink" href="#id58" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">responder</span> <span class="pre">client</span> <span class="pre"><target></span></code></strong> CLI subcommand generates a client from the
|
||
same import target as <code class="docutils literal notranslate"><span class="pre">responder</span> <span class="pre">run</span></code> — <code class="docutils literal notranslate"><span class="pre">--lang</span></code>, <code class="docutils literal notranslate"><span class="pre">--class-name</span></code>, and
|
||
<code class="docutils literal notranslate"><span class="pre">--output</span></code>/<code class="docutils literal notranslate"><span class="pre">-o</span></code> select the language, class name, and destination (stdout by
|
||
default).</p></li>
|
||
<li><p>Generated <strong>Python clients emit <code class="docutils literal notranslate"><span class="pre">TypedDict</span></code> definitions</strong> and <strong>TypeScript
|
||
clients exported interfaces</strong> for OpenAPI component schemas, used for the
|
||
request-body and success-response method signatures.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-5-0-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.4.0..v6.5.0">v6.5.0</a> - 2026-06-29<a class="headerlink" href="#v6-5-0-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release adding first-class client generation.</p>
|
||
<section id="id59">
|
||
<h3>Added<a class="headerlink" href="#id59" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">responder.ext.clientgen</span></code></strong> generates small Python, JavaScript,
|
||
TypeScript, Ruby, and PHP clients from Responder’s OpenAPI schema.
|
||
<code class="docutils literal notranslate"><span class="pre">generate_client(...)</span></code> returns source code, and <code class="docutils literal notranslate"><span class="pre">write_client(...)</span></code> writes a
|
||
module to disk.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">API.generate_client(...)</span></code></strong> is the app-level convenience wrapper:
|
||
<code class="docutils literal notranslate"><span class="pre">api.generate_client(class_name="ServiceClient")</span></code> returns source, while
|
||
<code class="docutils literal notranslate"><span class="pre">api.generate_client("clients/service.py",</span> <span class="pre">class_name="ServiceClient")</span></code> writes
|
||
a ready-to-import client module. Pass <code class="docutils literal notranslate"><span class="pre">language="typescript"</span></code> (or
|
||
<code class="docutils literal notranslate"><span class="pre">javascript</span></code>, <code class="docutils literal notranslate"><span class="pre">ruby</span></code>, <code class="docutils literal notranslate"><span class="pre">php</span></code>, <code class="docutils literal notranslate"><span class="pre">python</span></code>) to select the target.</p></li>
|
||
<li><p>Generated clients include method signatures from path/query parameters, JSON
|
||
request bodies, bearer/basic/API-key header helpers, structured <code class="docutils literal notranslate"><span class="pre">APIError</span></code>,
|
||
real HTTP transport, typed Python/TypeScript signatures where schema permits,
|
||
and a Python <code class="docutils literal notranslate"><span class="pre">session=</span></code> hook so the same generated client can call
|
||
<code class="docutils literal notranslate"><span class="pre">api.requests</span></code> in tests.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-4-0-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.3.1..v6.4.0">v6.4.0</a> - 2026-06-29<a class="headerlink" href="#v6-4-0-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release that makes typed path parameters and resumable
|
||
downloads much sharper in practice.</p>
|
||
<section id="id60">
|
||
<h3>Added<a class="headerlink" href="#id60" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Typed path parameters now work even on plain route segments.</strong> A route like
|
||
<code class="docutils literal notranslate"><span class="pre">/users/{id}</span></code> can now declare <code class="docutils literal notranslate"><span class="pre">id:</span> <span class="pre">int</span></code> (or <code class="docutils literal notranslate"><span class="pre">UUID</span></code>, etc.) and Responder
|
||
validates/coerces the path value into that type, returning a <code class="docutils literal notranslate"><span class="pre">422</span></code> on bad
|
||
input instead of passing a raw string through. WebSocket routes get the same
|
||
coercion and close invalid typed path parameters with <code class="docutils literal notranslate"><span class="pre">1008</span></code>.</p></li>
|
||
<li><p><strong>Path-parameter OpenAPI got smarter.</strong> The generated schema now reflects:</p>
|
||
<ul>
|
||
<li><p>a bare handler annotation on a plain <code class="docutils literal notranslate"><span class="pre">{id}</span></code> segment,</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">Path(...)</span></code> aliases/constraints/description metadata, and</p></li>
|
||
<li><p>the built-in <code class="docutils literal notranslate"><span class="pre">{id:uuid}</span></code> convertor as <code class="docutils literal notranslate"><span class="pre">{type:</span> <span class="pre">string,</span> <span class="pre">format:</span> <span class="pre">uuid}</span></code>.
|
||
Class-based views now generate method-specific parameters from <code class="docutils literal notranslate"><span class="pre">on_get</span></code> /
|
||
<code class="docutils literal notranslate"><span class="pre">on_post</span></code> / etc., so one method’s query parameters no longer disappear from
|
||
the schema.</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">If-Range</span></code> support for file responses.</strong> <code class="docutils literal notranslate"><span class="pre">resp.file()</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">resp.stream_file()</span></code>, and <code class="docutils literal notranslate"><span class="pre">resp.download()</span></code> now honor <code class="docutils literal notranslate"><span class="pre">If-Range</span></code> so a
|
||
stale resumable-download request automatically falls back to the full body
|
||
instead of returning a partial response for the wrong representation.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-3-1-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.3.0..v6.3.1">v6.3.1</a> - 2026-06-29<a class="headerlink" href="#v6-3-1-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<section id="id61">
|
||
<h3>Fixed<a class="headerlink" href="#id61" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>OpenAPI now emits query/header/cookie/path parameters at the <strong>operation</strong>
|
||
level rather than the path-item level. The path-item placement (present since
|
||
the typed-OpenAPI feature in 5.0) leaked a route’s parameters onto sibling
|
||
methods sharing the same path — e.g. a <code class="docutils literal notranslate"><span class="pre">@api.post</span></code> inherited a <code class="docutils literal notranslate"><span class="pre">@api.get</span></code>’s
|
||
query parameters. Each operation now carries only its own parameters (also the
|
||
placement most tooling and codegen expect).</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-3-0-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.2.0..v6.3.0">v6.3.0</a> - 2026-06-29<a class="headerlink" href="#v6-3-0-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release adding sorting & filtering helpers that complete
|
||
the list-endpoint story alongside pagination.</p>
|
||
<section id="id62">
|
||
<h3>Added<a class="headerlink" href="#id62" title="Link to this heading">¶</a></h3>
|
||
<ul>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">responder.ext.query</span></code></strong> — in-memory helpers for list endpoints (dicts or
|
||
objects, no ORM coupling):</p>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">sort_items(items,</span> <span class="pre">spec,</span> <span class="pre">*,</span> <span class="pre">allowed=None)</span></code></strong> sorts by a <code class="docutils literal notranslate"><span class="pre">name,-created</span></code>
|
||
spec (<code class="docutils literal notranslate"><span class="pre">-</span></code> = descending, multiple keys, <code class="docutils literal notranslate"><span class="pre">None</span></code> sorts last). Pass
|
||
<code class="docutils literal notranslate"><span class="pre">allowed=</span></code> for a client-supplied sort so users can’t order by arbitrary
|
||
attributes — an out-of-list (or incomparable) field returns <code class="docutils literal notranslate"><span class="pre">400</span></code>.
|
||
<code class="docutils literal notranslate"><span class="pre">parse_sort</span></code> is exposed for sorting in the database yourself.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">filter_items(items,</span> <span class="pre">filters)</span></code></strong> applies <code class="docutils literal notranslate"><span class="pre">field</span> <span class="pre">==</span> <span class="pre">value</span></code> equality and
|
||
skips <code class="docutils literal notranslate"><span class="pre">None</span></code> values, so optional <code class="docutils literal notranslate"><span class="pre">Query</span></code> markers pass straight through.</p></li>
|
||
</ul>
|
||
<p>Together with <code class="docutils literal notranslate"><span class="pre">Query</span></code> markers and <code class="docutils literal notranslate"><span class="pre">responder.ext.pagination</span></code> they make a
|
||
complete filter → sort → paginate pipeline.</p>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-2-0-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.1.0..v6.2.0">v6.2.0</a> - 2026-06-29<a class="headerlink" href="#v6-2-0-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release adding pagination helpers for list endpoints.</p>
|
||
<section id="id63">
|
||
<h3>Added<a class="headerlink" href="#id63" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">responder.ext.pagination</span></code></strong> — a generic <code class="docutils literal notranslate"><span class="pre">Page[T]</span></code> response envelope
|
||
(<code class="docutils literal notranslate"><span class="pre">items</span></code>, <code class="docutils literal notranslate"><span class="pre">total</span></code>, <code class="docutils literal notranslate"><span class="pre">page</span></code>, <code class="docutils literal notranslate"><span class="pre">size</span></code>, <code class="docutils literal notranslate"><span class="pre">pages</span></code>) and a <code class="docutils literal notranslate"><span class="pre">paginate(items,</span> <span class="pre">*,</span> <span class="pre">page,</span> <span class="pre">size,</span> <span class="pre">total=None)</span></code> helper. <code class="docutils literal notranslate"><span class="pre">paginate</span></code> slices an in-memory collection by
|
||
default, or wraps an already-sliced page when you pass <code class="docutils literal notranslate"><span class="pre">total=</span></code> (e.g. a
|
||
<code class="docutils literal notranslate"><span class="pre">LIMIT/OFFSET</span></code> query). Pairs with the typed <code class="docutils literal notranslate"><span class="pre">Query</span></code> markers and
|
||
<code class="docutils literal notranslate"><span class="pre">response_model=Page[Item]</span></code> — the OpenAPI schema documents the envelope inline,
|
||
referencing your element model.</p></li>
|
||
<li><p>Parametrized generic models (e.g. <code class="docutils literal notranslate"><span class="pre">Page[Item]</span></code>) are now emitted <strong>inline</strong> in
|
||
OpenAPI (referencing their element components) rather than registered under a
|
||
bracketed — and spec-invalid — component name.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-1-0-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.0.2..v6.1.0">v6.1.0</a> - 2026-06-29<a class="headerlink" href="#v6-1-0-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release that makes Server-Sent Events production-grade.</p>
|
||
<section id="id64">
|
||
<h3>Added<a class="headerlink" href="#id64" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Production-grade <code class="docutils literal notranslate"><span class="pre">resp.sse</span></code>.</strong> Server-Sent Events gain:</p>
|
||
<ul>
|
||
<li><p><strong>JSON-encoded data</strong> — a <code class="docutils literal notranslate"><span class="pre">data</span></code> value that is a <code class="docutils literal notranslate"><span class="pre">dict</span></code>/<code class="docutils literal notranslate"><span class="pre">list</span></code> is
|
||
serialized automatically (great for structured/LLM streaming).</p></li>
|
||
<li><p><strong>Comment frames</strong> via <code class="docutils literal notranslate"><span class="pre">{"comment":</span> <span class="pre">"..."}</span></code> (and raw <code class="docutils literal notranslate"><span class="pre">bytes</span></code> pass
|
||
through verbatim).</p></li>
|
||
<li><p><strong>Opt-in heartbeat</strong> — <code class="docutils literal notranslate"><span class="pre">@resp.sse(heartbeat=15)</span></code> emits a keepalive comment
|
||
during idle periods (without interrupting the producer mid-event), so
|
||
long-lived streams survive proxy idle-timeouts.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">X-Accel-Buffering:</span> <span class="pre">no</span></code></strong> so events flush immediately behind nginx and
|
||
similar proxies.</p></li>
|
||
<li><p>The <code class="docutils literal notranslate"><span class="pre">@resp.sse(heartbeat=...)</span></code> decorator-with-arguments form.</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">req.last_event_id</span></code></strong> exposes the SSE <code class="docutils literal notranslate"><span class="pre">Last-Event-ID</span></code> request header, so a
|
||
handler can resume a stream where a reconnecting client left off.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-0-2-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.0.1..v6.0.2">v6.0.2</a> - 2026-06-29<a class="headerlink" href="#v6-0-2-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<p>A bugfix release closing a set of cross-feature interaction defects found by an
|
||
adversarial review of the 5.1->6.0 work — including two remotely-triggerable
|
||
500s and a bypass of <code class="docutils literal notranslate"><span class="pre">max_request_size</span></code> on multipart uploads. Upgrading from
|
||
6.0.x is strongly recommended.</p>
|
||
<section id="id65">
|
||
<h3>Fixed<a class="headerlink" href="#id65" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Remote 500 on file endpoints.</strong> An <code class="docutils literal notranslate"><span class="pre">If-Modified-Since</span></code> header with a <code class="docutils literal notranslate"><span class="pre">-0000</span></code>
|
||
timezone crashed every conditional file response (a naive-vs-aware datetime
|
||
comparison sat outside the try/except). Both sides are now normalized to UTC.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">max_request_size</span></code> bypass + “Stream consumed” 500 on multipart.</strong> Parsing a
|
||
form/file body (<code class="docutils literal notranslate"><span class="pre">Form()</span></code>/<code class="docutils literal notranslate"><span class="pre">File()</span></code> markers or <code class="docutils literal notranslate"><span class="pre">req.media("files")</span></code>) now buffers
|
||
through the size-checked body, so the cap is enforced (<code class="docutils literal notranslate"><span class="pre">413</span></code>) and the body
|
||
stays readable afterward (<code class="docutils literal notranslate"><span class="pre">req.content</span></code>, <code class="docutils literal notranslate"><span class="pre">media("form")</span></code>, …) in any order.
|
||
(This trades 5.5’s spool-to-disk streaming for correctness; for true streaming
|
||
uploads, read <code class="docutils literal notranslate"><span class="pre">req.stream()</span></code> directly.)</p></li>
|
||
<li><p><strong>Recursive Pydantic models</strong> registered an empty self-referential OpenAPI
|
||
component; the real schema body is now emitted.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">APIKeyAuth(location="query")</span></code></strong> crashed on WebSocket routes (it read
|
||
<code class="docutils literal notranslate"><span class="pre">.params</span></code>, which a Starlette WebSocket lacks); it now falls back to
|
||
<code class="docutils literal notranslate"><span class="pre">.query_params</span></code>.</p></li>
|
||
<li><p><strong>Callable-instance generator dependencies</strong> (a class whose <code class="docutils literal notranslate"><span class="pre">__call__</span></code> yields)
|
||
now run their teardown instead of leaking the generator object as the value.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">dependency_overrides</span></code></strong> now reaches into the app-scoped graph: overriding a
|
||
dependency that an <code class="docutils literal notranslate"><span class="pre">app</span></code>-scoped dependency depends on resolves correctly (was a
|
||
<code class="docutils literal notranslate"><span class="pre">DependencyScopeError</span></code> / stale cached value), and overrides restore per-key so
|
||
nested blocks don’t clobber each other.</p></li>
|
||
<li><p><strong>Conditional responses.</strong> A <code class="docutils literal notranslate"><span class="pre">304</span></code> now carries the negotiated <code class="docutils literal notranslate"><span class="pre">Vary</span></code> header,
|
||
and a <code class="docutils literal notranslate"><span class="pre">Range</span></code> request with a matching validator returns <code class="docutils literal notranslate"><span class="pre">304</span></code> rather than a
|
||
<code class="docutils literal notranslate"><span class="pre">206</span></code> body.</p></li>
|
||
<li><p>OpenAPI now logs a warning on a component <strong>name collision</strong> (two distinct
|
||
models sharing a <code class="docutils literal notranslate"><span class="pre">__name__</span></code>) instead of silently serving one for both.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-0-1-2026-06-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v6.0.0..v6.0.1">v6.0.1</a> - 2026-06-29<a class="headerlink" href="#v6-0-1-2026-06-29" title="Link to this heading">¶</a></h2>
|
||
<section id="id66">
|
||
<h3>Fixed<a class="headerlink" href="#id66" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">Annotated[...]</span></code> markers with a <code class="docutils literal notranslate"><span class="pre">None</span></code> default</strong> (e.g.
|
||
<code class="docutils literal notranslate"><span class="pre">token:</span> <span class="pre">Annotated[str,</span> <span class="pre">Header(None)]</span> <span class="pre">=</span> <span class="pre">None</span></code>) were not detected on Python
|
||
3.10, where <code class="docutils literal notranslate"><span class="pre">get_type_hints</span></code> implicitly wraps the annotation in <code class="docutils literal notranslate"><span class="pre">Optional</span></code> —
|
||
the marker is now found through the <code class="docutils literal notranslate"><span class="pre">Union</span></code>. (Latent since 5.3.)</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v6-0-0-2026-06-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v5.6.0..v6.0.0">v6.0.0</a> - 2026-06-28<a class="headerlink" href="#v6-0-0-2026-06-28" title="Link to this heading">¶</a></h2>
|
||
<p>A small, deliberate major release: <strong>no new features</strong> — it removes the
|
||
deprecation shims introduced during 5.x and flips a few defaults to the
|
||
more-correct behavior. Every change was announced with a <code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code>
|
||
or an opt-in knob during 5.x, so code that runs clean under
|
||
<code class="docutils literal notranslate"><span class="pre">-W</span> <span class="pre">error::DeprecationWarning</span></code> on 5.6 upgrades without surprises. See the
|
||
<a class="reference external" href="https://github.com/kennethreitz/responder/blob/main/docs/migration-v6.md">v6 migration guide</a>.</p>
|
||
<section id="id67">
|
||
<h3>Removed<a class="headerlink" href="#id67" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>The case-insensitive <code class="docutils literal notranslate"><span class="pre">req.method</span></code> comparison shim.</strong> <code class="docutils literal notranslate"><span class="pre">req.method</span></code> is now a
|
||
plain uppercase <code class="docutils literal notranslate"><span class="pre">str</span></code>; compare against uppercase literals (<code class="docutils literal notranslate"><span class="pre">req.method</span> <span class="pre">==</span> <span class="pre">"GET"</span></code>). (Announced in 5.0.)</p></li>
|
||
<li><p><strong>The single-unnamed-parameter dependency-provider shim.</strong> A provider’s
|
||
request parameter must be named <code class="docutils literal notranslate"><span class="pre">req</span></code>/<code class="docutils literal notranslate"><span class="pre">request</span></code> or annotated <code class="docutils literal notranslate"><span class="pre">Request</span></code>;
|
||
otherwise resolution raises <code class="docutils literal notranslate"><span class="pre">DependencyResolutionError</span></code>. (Announced in 5.0.)</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id68">
|
||
<h3>Changed<a class="headerlink" href="#id68" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">req.media("files")</span></code></strong> returns streaming <code class="docutils literal notranslate"><span class="pre">UploadFile</span></code> objects keyed by
|
||
field name instead of a fully-buffered bytes-dict; <code class="docutils literal notranslate"><span class="pre">File()</span></code> markers are the
|
||
typed equivalent. (Deprecated in 5.6.)</p></li>
|
||
<li><p><strong>JSON defaults to <code class="docutils literal notranslate"><span class="pre">ensure_ascii=False</span></code></strong> (raw UTF-8). This changes response
|
||
bytes and <code class="docutils literal notranslate"><span class="pre">auto_etag</span></code> values for non-ASCII payloads; pass
|
||
<code class="docutils literal notranslate"><span class="pre">API(json_ensure_ascii=True)</span></code> to restore <code class="docutils literal notranslate"><span class="pre">\uXXXX</span></code> escaping. (Knob added in 5.6.)</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">Vary:</span> <span class="pre">Accept</span></code></strong> is now sent by default on content-negotiated responses
|
||
(correct for shared caches); pass <code class="docutils literal notranslate"><span class="pre">API(auto_vary=False)</span></code> to opt out. (Opt-in
|
||
added in 5.1.)</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">Route.__hash__</span></code></strong> no longer includes <code class="docutils literal notranslate"><span class="pre">before_request</span></code>, so routes that
|
||
compare equal now hash equal.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v5-6-0-2026-06-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v5.5.0..v5.6.0">v5.6.0</a> - 2026-06-28<a class="headerlink" href="#v5-6-0-2026-06-28" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release that stages the breaking changes coming in
|
||
Responder 6.0 — adding the opt-in knobs and deprecation warnings so you can
|
||
adapt on 5.x first. See the <a class="reference external" href="https://github.com/kennethreitz/responder/blob/main/docs/migration-v6.md">v6 migration guide</a>.</p>
|
||
<section id="id69">
|
||
<h3>Added<a class="headerlink" href="#id69" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">API(json_ensure_ascii=...)</span></code></strong> controls JSON non-ASCII escaping. The default
|
||
stays <code class="docutils literal notranslate"><span class="pre">True</span></code> (escape as <code class="docutils literal notranslate"><span class="pre">\uXXXX</span></code>) in 5.x and flips to <code class="docutils literal notranslate"><span class="pre">False</span></code> (raw UTF-8) in
|
||
6.0; set it explicitly to lock in either behavior.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id70">
|
||
<h3>Deprecated<a class="headerlink" href="#id70" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">req.media("files")</span></code></strong> (the fully-buffered bytes-dict) now emits a
|
||
<code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code>. In 6.0 it returns streaming <code class="docutils literal notranslate"><span class="pre">UploadFile</span></code> objects; use
|
||
<code class="docutils literal notranslate"><span class="pre">File()</span></code> markers for the new API today. The bytes-dict is still returned in
|
||
5.x.</p></li>
|
||
<li><p>Documented the project’s <strong>deprecation policy</strong> and the full 6.0 breaking-change
|
||
list in <code class="docutils literal notranslate"><span class="pre">docs/migration-v6.md</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v5-5-0-2026-06-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v5.4.0..v5.5.0">v5.5.0</a> - 2026-06-28<a class="headerlink" href="#v5-5-0-2026-06-28" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release adding type-driven file uploads and form fields,
|
||
completing the typed-parameter surface. No existing call signatures change.</p>
|
||
<section id="id71">
|
||
<h3>Added<a class="headerlink" href="#id71" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">File()</span></code> and <code class="docutils literal notranslate"><span class="pre">Form()</span></code> markers.</strong> <code class="docutils literal notranslate"><span class="pre">File()</span></code> injects an uploaded file as an
|
||
<code class="docutils literal notranslate"><span class="pre">UploadFile</span></code> (read with <code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">f.read()</span></code>, or stream it in chunks — large
|
||
uploads are spooled to disk by Starlette’s parser rather than held in
|
||
memory); <code class="docutils literal notranslate"><span class="pre">Form()</span></code> injects a form field (urlencoded or multipart), coerced and
|
||
validated like <code class="docutils literal notranslate"><span class="pre">Query()</span></code>. A sequence annotation (<code class="docutils literal notranslate"><span class="pre">list[UploadFile]</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">list[str]</span></code>) collects repeated fields. Both support the <code class="docutils literal notranslate"><span class="pre">Annotated[...]</span></code> form.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">responder.UploadFile</span></code></strong> is exported for annotating upload parameters.</p></li>
|
||
<li><p><strong>Multipart OpenAPI.</strong> Routes with <code class="docutils literal notranslate"><span class="pre">File()</span></code>/<code class="docutils literal notranslate"><span class="pre">Form()</span></code> markers generate a
|
||
<code class="docutils literal notranslate"><span class="pre">multipart/form-data</span></code> (or <code class="docutils literal notranslate"><span class="pre">application/x-www-form-urlencoded</span></code>) request body —
|
||
files as <code class="docutils literal notranslate"><span class="pre">{type:</span> <span class="pre">string,</span> <span class="pre">format:</span> <span class="pre">binary}</span></code> — so the interactive docs show a
|
||
file picker.</p></li>
|
||
</ul>
|
||
<p>The existing <code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">req.media("files")</span></code> bytes-dict contract is unchanged.</p>
|
||
</section>
|
||
</section>
|
||
<section id="v5-4-0-2026-06-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v5.3.0..v5.4.0">v5.4.0</a> - 2026-06-28<a class="headerlink" href="#v5-4-0-2026-06-28" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release focused on testing, operations, and HTTP
|
||
correctness. No existing call signatures change.</p>
|
||
<section id="id72">
|
||
<h3>Added<a class="headerlink" href="#id72" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">api.dependency_overrides(**overrides)</span></code></strong> — a context manager that swaps
|
||
dependencies for tests and restores them on exit. Values may be bare objects
|
||
(wrapped automatically) or provider callables (which still receive
|
||
sub-dependencies and the request). Overrides are request-scoped, so they
|
||
replace and bypass the cache of an <code class="docutils literal notranslate"><span class="pre">app</span></code>-scoped dependency too.</p></li>
|
||
<li><p><strong>Health checks.</strong> <code class="docutils literal notranslate"><span class="pre">api.add_health_check(name,</span> <span class="pre">check)</span></code> registers a readiness
|
||
check (sync or async; passes unless it returns <code class="docutils literal notranslate"><span class="pre">False</span></code> or raises) and
|
||
<code class="docutils literal notranslate"><span class="pre">API(health_route="/health")</span></code> serves the aggregate — <code class="docutils literal notranslate"><span class="pre">200</span></code> with per-check
|
||
JSON when all pass, <code class="docutils literal notranslate"><span class="pre">503</span></code> otherwise. The route is excluded from the OpenAPI
|
||
schema.</p></li>
|
||
<li><p><strong>Named routes.</strong> <code class="docutils literal notranslate"><span class="pre">@api.route(...,</span> <span class="pre">name="...")</span></code> (and the verb decorators /
|
||
<code class="docutils literal notranslate"><span class="pre">add_route</span></code>) name a route so <code class="docutils literal notranslate"><span class="pre">api.url_for("name",</span> <span class="pre">**params)</span></code> can reverse it by
|
||
string — decoupling URL generation from the endpoint’s function identity
|
||
(so lambdas and shared names are addressable). Works for WebSocket routes too.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id73">
|
||
<h3>Fixed<a class="headerlink" href="#id73" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Conditional requests for served files.</strong> <code class="docutils literal notranslate"><span class="pre">resp.file()</span></code>, <code class="docutils literal notranslate"><span class="pre">resp.stream_file()</span></code>,
|
||
and <code class="docutils literal notranslate"><span class="pre">resp.download()</span></code> now set a stat-based weak <code class="docutils literal notranslate"><span class="pre">ETag</span></code> and <code class="docutils literal notranslate"><span class="pre">Last-Modified</span></code> by
|
||
default, so <code class="docutils literal notranslate"><span class="pre">If-None-Match</span></code> / <code class="docutils literal notranslate"><span class="pre">If-Modified-Since</span></code> get a <code class="docutils literal notranslate"><span class="pre">304</span></code> (and <code class="docutils literal notranslate"><span class="pre">file()</span></code>
|
||
no longer reads the whole file to hash it under <code class="docutils literal notranslate"><span class="pre">auto_etag</span></code>). Range requests
|
||
are unaffected. Pass <code class="docutils literal notranslate"><span class="pre">conditional=False</span></code> to opt out.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v5-3-0-2026-06-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v5.2.0..v5.3.0">v5.3.0</a> - 2026-06-28<a class="headerlink" href="#v5-3-0-2026-06-28" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release that finishes the type-driven I/O and OpenAPI
|
||
authoring story: <code class="docutils literal notranslate"><span class="pre">Annotated[]</span></code> markers, generic response models, and
|
||
first-class route/operation metadata. No existing call signatures change.</p>
|
||
<section id="id74">
|
||
<h3>Added<a class="headerlink" href="#id74" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">Annotated[]</span></code> marker form.</strong> <code class="docutils literal notranslate"><span class="pre">Query</span></code>/<code class="docutils literal notranslate"><span class="pre">Header</span></code>/<code class="docutils literal notranslate"><span class="pre">Cookie</span></code>/<code class="docutils literal notranslate"><span class="pre">Path</span></code> markers can
|
||
now be written as <code class="docutils literal notranslate"><span class="pre">q:</span> <span class="pre">Annotated[int,</span> <span class="pre">Query(ge=1)]</span></code> (PEP 593), keeping the
|
||
parameter’s default value in the usual slot — the FastAPI-familiar style — in
|
||
addition to the existing <code class="docutils literal notranslate"><span class="pre">q:</span> <span class="pre">int</span> <span class="pre">=</span> <span class="pre">Query(...)</span></code> form. Constraints, aliases,
|
||
and OpenAPI emission work identically either way.</p></li>
|
||
<li><p><strong>Generic <code class="docutils literal notranslate"><span class="pre">response_model</span></code>.</strong> <code class="docutils literal notranslate"><span class="pre">response_model=list[Model]</span></code>, tuples, and unions
|
||
(<code class="docutils literal notranslate"><span class="pre">Model</span> <span class="pre">|</span> <span class="pre">ErrorModel</span></code>) are now validated and serialized via a <code class="docutils literal notranslate"><span class="pre">TypeAdapter</span></code>
|
||
and documented correctly in OpenAPI — an <code class="docutils literal notranslate"><span class="pre">array</span></code> with an <code class="docutils literal notranslate"><span class="pre">items</span></code> <code class="docutils literal notranslate"><span class="pre">$ref</span></code> for a
|
||
list, <code class="docutils literal notranslate"><span class="pre">oneOf</span></code>/<code class="docutils literal notranslate"><span class="pre">anyOf</span></code> for a union, with the referenced models hoisted into
|
||
<code class="docutils literal notranslate"><span class="pre">components/schemas</span></code>. (<code class="docutils literal notranslate"><span class="pre">response_model=list[Model]</span></code> previously registered a
|
||
bogus schema named <code class="docutils literal notranslate"><span class="pre">list</span></code>.) A bare <code class="docutils literal notranslate"><span class="pre">-></span> <span class="pre">list[Model]</span></code> <em>return annotation</em> still
|
||
appears in the schema but stays un-validated at runtime, so existing handlers
|
||
returning loose data keep working.</p></li>
|
||
<li><p><strong>Route/operation metadata.</strong> <code class="docutils literal notranslate"><span class="pre">tags</span></code>, <code class="docutils literal notranslate"><span class="pre">summary</span></code>, <code class="docutils literal notranslate"><span class="pre">description</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">operation_id</span></code>, and <code class="docutils literal notranslate"><span class="pre">deprecated</span></code> kwargs on <code class="docutils literal notranslate"><span class="pre">@api.route</span></code> (and the verb
|
||
decorators) flow into the generated OpenAPI operation; a docstring-YAML block
|
||
still overrides them.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">API(openapi_servers=[...])</span></code></strong> populates the OpenAPI <code class="docutils literal notranslate"><span class="pre">servers</span></code> list.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v5-2-0-2026-06-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v5.1.0..v5.2.0">v5.2.0</a> - 2026-06-28<a class="headerlink" href="#v5-2-0-2026-06-28" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible release that rounds out the security story: a batteries-
|
||
included authentication extension that wires straight into OpenAPI (so the
|
||
interactive docs get an <strong>Authorize</strong> button), and an opt-in security-headers
|
||
middleware. No existing call signatures change.</p>
|
||
<section id="id75">
|
||
<h3>Added<a class="headerlink" href="#id75" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">responder.ext.auth</span></code></strong> — <code class="docutils literal notranslate"><span class="pre">BearerAuth</span></code>, <code class="docutils literal notranslate"><span class="pre">BasicAuth</span></code>, and <code class="docutils literal notranslate"><span class="pre">APIKeyAuth</span></code>
|
||
schemes. Each is a callable that extracts the credential, runs your
|
||
(sync or async) <code class="docutils literal notranslate"><span class="pre">verify</span></code> callback, and returns the principal — or raises
|
||
<code class="docutils literal notranslate"><span class="pre">401</span></code> with the correct <code class="docutils literal notranslate"><span class="pre">WWW-Authenticate</span></code> challenge. Use one as a dependency
|
||
to inject the principal into a handler, or call it directly. For static
|
||
secrets, pass them inline (<code class="docutils literal notranslate"><span class="pre">BearerAuth(tokens=[...])</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">APIKeyAuth(keys=[...])</span></code>, <code class="docutils literal notranslate"><span class="pre">BasicAuth(credentials={...})</span></code>) and the scheme
|
||
compares them in constant time.</p></li>
|
||
<li><p><strong>OpenAPI security schemes.</strong> <code class="docutils literal notranslate"><span class="pre">api.add_security_scheme(name,</span> <span class="pre">scheme)</span></code> (or
|
||
<code class="docutils literal notranslate"><span class="pre">scheme.register(api)</span></code>) populates <code class="docutils literal notranslate"><span class="pre">components.securitySchemes</span></code> so Swagger /
|
||
ReDoc render an <strong>Authorize</strong> button. A <code class="docutils literal notranslate"><span class="pre">security=</span></code> kwarg on routes (and the
|
||
verb decorators) marks which operations require auth; <code class="docutils literal notranslate"><span class="pre">default=True</span></code> requires
|
||
a scheme on every operation.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">API(security_headers=True)</span></code></strong> and <strong><code class="docutils literal notranslate"><span class="pre">responder.middleware.SecurityHeadersMiddleware</span></code></strong>
|
||
— add <code class="docutils literal notranslate"><span class="pre">X-Content-Type-Options:</span> <span class="pre">nosniff</span></code>, <code class="docutils literal notranslate"><span class="pre">X-Frame-Options:</span> <span class="pre">DENY</span></code>, and
|
||
<code class="docutils literal notranslate"><span class="pre">Referrer-Policy:</span> <span class="pre">strict-origin-when-cross-origin</span></code> to every response (opt-in).
|
||
Pass a dict to add a <code class="docutils literal notranslate"><span class="pre">content_security_policy</span></code> / <code class="docutils literal notranslate"><span class="pre">permissions_policy</span></code> or
|
||
override any header. Headers a handler set itself are preserved.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id76">
|
||
<h3>Changed<a class="headerlink" href="#id76" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Dependency providers may now be <strong>callable instances</strong> with an async
|
||
<code class="docutils literal notranslate"><span class="pre">__call__</span></code> (previously only plain async functions were awaited; an async
|
||
<code class="docutils literal notranslate"><span class="pre">__call__</span></code> was mistakenly run in a thread). This is what lets an auth scheme
|
||
object be used directly as a dependency.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v5-1-0-2026-06-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v5.0.0..v5.1.0">v5.1.0</a> - 2026-06-28<a class="headerlink" href="#v5-1-0-2026-06-28" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible follow-up that finishes what v5 started: it makes the
|
||
type-driven OpenAPI and typed-parameter features correct for the common cases
|
||
they missed, turns the documented-but-absent HSTS header into a real one, and
|
||
adds the small ergonomics the typed surface implies. No existing call
|
||
signatures change.</p>
|
||
<section id="id77">
|
||
<h3>Fixed<a class="headerlink" href="#id77" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Type-driven OpenAPI now emits valid documents for nested models.</strong> A model
|
||
containing another model previously produced a dangling <code class="docutils literal notranslate"><span class="pre">#/$defs/...</span></code>
|
||
reference (the nested schema was never registered as a component), so Swagger
|
||
UI / ReDoc / codegen could not resolve it. Each nested model is now hoisted
|
||
into its own top-level <code class="docutils literal notranslate"><span class="pre">components/schemas</span></code> entry with rewritten <code class="docutils literal notranslate"><span class="pre">$ref</span></code>s.</p></li>
|
||
<li><p><strong>OpenAPI output matches the declared dialect.</strong> Under a <code class="docutils literal notranslate"><span class="pre">3.0.x</span></code> version,
|
||
<code class="docutils literal notranslate"><span class="pre">Optional[...]</span></code> fields (which Pydantic v2 emits as <code class="docutils literal notranslate"><span class="pre">anyOf:</span> <span class="pre">[...,</span> <span class="pre">{type:</span> <span class="pre">null}]</span></code>,
|
||
invalid in 3.0) are down-converted to <code class="docutils literal notranslate"><span class="pre">nullable</span></code>, and array-valued <code class="docutils literal notranslate"><span class="pre">examples</span></code>
|
||
are singularized — so the document validates. <code class="docutils literal notranslate"><span class="pre">3.1</span></code> output is unchanged.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">Query()</span></code>/<code class="docutils literal notranslate"><span class="pre">Header()</span></code>/<code class="docutils literal notranslate"><span class="pre">Cookie()</span></code>/<code class="docutils literal notranslate"><span class="pre">Path()</span></code> markers now enforce their
|
||
constraints.</strong> <code class="docutils literal notranslate"><span class="pre">Query(min_length=3)</span></code>, <code class="docutils literal notranslate"><span class="pre">Query(gt=0)</span></code>, etc. were silently
|
||
ignored (validation was built from the bare annotation); they now apply and
|
||
return <code class="docutils literal notranslate"><span class="pre">422</span></code> on violation, and a typo’d keyword (e.g. <code class="docutils literal notranslate"><span class="pre">Query(dafault=5)</span></code>) now
|
||
raises <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> at definition time instead of silently making the parameter
|
||
required. A marker’s <code class="docutils literal notranslate"><span class="pre">description</span></code>/<code class="docutils literal notranslate"><span class="pre">deprecated</span></code> now appear in the OpenAPI spec.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">enable_hsts=True</span></code> now sends a real <code class="docutils literal notranslate"><span class="pre">Strict-Transport-Security</span></code> header</strong>
|
||
(in addition to the existing HTTP→HTTPS redirect). It previously only
|
||
redirected, despite the docs promising browsers “see the HSTS header.”</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id78">
|
||
<h3>Added<a class="headerlink" href="#id78" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>HTTP verb shortcut decorators</strong> — <code class="docutils literal notranslate"><span class="pre">@api.get</span></code>, <code class="docutils literal notranslate"><span class="pre">@api.post</span></code>, <code class="docutils literal notranslate"><span class="pre">@api.put</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">@api.patch</span></code>, <code class="docutils literal notranslate"><span class="pre">@api.delete</span></code>, and <code class="docutils literal notranslate"><span class="pre">@api.websocket_route</span></code>, plus the same on
|
||
route groups. Registering <code class="docutils literal notranslate"><span class="pre">@api.get("/x")</span></code> and <code class="docutils literal notranslate"><span class="pre">@api.post("/x")</span></code> as separate
|
||
handlers on one path now works (same-path routes are allowed when their
|
||
methods are disjoint).</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">resp.delete_cookie(key,</span> <span class="pre">...)</span></code></strong> — expire a cookie on the client (mirrors
|
||
<code class="docutils literal notranslate"><span class="pre">set_cookie</span></code>’s <code class="docutils literal notranslate"><span class="pre">path</span></code>/<code class="docutils literal notranslate"><span class="pre">domain</span></code>/<code class="docutils literal notranslate"><span class="pre">secure</span></code>/<code class="docutils literal notranslate"><span class="pre">httponly</span></code>/<code class="docutils literal notranslate"><span class="pre">samesite</span></code>).</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">resp.vary(*fields)</span></code></strong> — add field names to the <code class="docutils literal notranslate"><span class="pre">Vary</span></code> header (merged and
|
||
de-duplicated). New <code class="docutils literal notranslate"><span class="pre">API(auto_vary=True)</span></code> emits <code class="docutils literal notranslate"><span class="pre">Vary:</span> <span class="pre">Accept</span></code> on
|
||
content-negotiated responses (correct for shared caches); off by default,
|
||
slated to default on in 6.0.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">responder.middleware.HSTSMiddleware</span></code></strong> — the HSTS header middleware, usable
|
||
directly via <code class="docutils literal notranslate"><span class="pre">add_middleware</span></code> to customize <code class="docutils literal notranslate"><span class="pre">max_age</span></code>/<code class="docutils literal notranslate"><span class="pre">preload</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v5-0-0-2026-06-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v4.1.0..v5.0.0">v5.0.0</a> - 2026-06-28<a class="headerlink" href="#v5-0-0-2026-06-28" title="Link to this heading">¶</a></h2>
|
||
<p>A major release: fully type-driven request/response I/O, composable dependency
|
||
injection, plan-driven OpenAPI, secure-by-default sessions, and a deferred
|
||
middleware stack — layered onto the unchanged <code class="docutils literal notranslate"><span class="pre">(req,</span> <span class="pre">resp)</span></code> core. Breaking
|
||
changes are staged behind the <a class="reference external" href="https://github.com/kennethreitz/responder/blob/main/docs/migration-v5.md">v5 migration guide</a>.</p>
|
||
<section id="id79">
|
||
<h3>Added<a class="headerlink" href="#id79" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Type-hint-driven OpenAPI.</strong> The schema is now generated from each route’s
|
||
methods, body/response models, and <code class="docutils literal notranslate"><span class="pre">Query</span></code>/<code class="docutils literal notranslate"><span class="pre">Header</span></code>/<code class="docutils literal notranslate"><span class="pre">Cookie</span></code> markers — so
|
||
routes <strong>without</strong> a YAML docstring now appear in the spec (with parameters,
|
||
request/response schemas, and an automatic <code class="docutils literal notranslate"><span class="pre">422</span></code> for validating routes).
|
||
Docstring YAML is deep-merged on top as an override. New
|
||
<code class="docutils literal notranslate"><span class="pre">@api.route(...,</span> <span class="pre">include_in_schema=False)</span></code> hides a route; internal routes
|
||
(schema/docs/static/metrics) are auto-excluded.</p></li>
|
||
<li><p><strong>Typed parameter markers.</strong> <code class="docutils literal notranslate"><span class="pre">Query()</span></code>, <code class="docutils literal notranslate"><span class="pre">Header()</span></code>, <code class="docutils literal notranslate"><span class="pre">Cookie()</span></code>, and <code class="docutils literal notranslate"><span class="pre">Path()</span></code>
|
||
(exported from <code class="docutils literal notranslate"><span class="pre">responder</span></code>) inject validated, type-coerced query parameters,
|
||
headers, cookies, and path parameters as handler arguments —
|
||
<code class="docutils literal notranslate"><span class="pre">def</span> <span class="pre">search(req,</span> <span class="pre">resp,</span> <span class="pre">*,</span> <span class="pre">q:</span> <span class="pre">str</span> <span class="pre">=</span> <span class="pre">Query(...),</span> <span class="pre">limit:</span> <span class="pre">int</span> <span class="pre">=</span> <span class="pre">Query(10))</span></code> —
|
||
with <code class="docutils literal notranslate"><span class="pre">422</span></code> on a missing required value or a validation failure. Supports
|
||
defaults, aliases, and sequence types (<code class="docutils literal notranslate"><span class="pre">list[int]</span></code> from repeated query keys).</p></li>
|
||
<li><p><strong>Return annotation as <code class="docutils literal notranslate"><span class="pre">response_model</span></code>.</strong> A Pydantic return annotation
|
||
(<code class="docutils literal notranslate"><span class="pre">def</span> <span class="pre">handler(req,</span> <span class="pre">resp)</span> <span class="pre">-></span> <span class="pre">ItemOut</span></code>) now validates/serializes the response
|
||
against that model (coerce types, strip undeclared fields), the same as an
|
||
explicit <code class="docutils literal notranslate"><span class="pre">response_model=</span></code>.</p></li>
|
||
<li><p><strong>Composable dependency injection.</strong> A dependency provider can now depend on
|
||
<em>other</em> providers by declaring them as parameters — resolved recursively,
|
||
memoized across the whole request graph, torn down in reverse-topological
|
||
order, with cycle detection. App-scoped dependencies may compose with other
|
||
app-scoped ones (but never with the request or request-scoped deps).
|
||
Providers receive the request only via a <code class="docutils literal notranslate"><span class="pre">req</span></code>/<code class="docutils literal notranslate"><span class="pre">request</span></code> parameter or a
|
||
<code class="docutils literal notranslate"><span class="pre">Request</span></code>/<code class="docutils literal notranslate"><span class="pre">WebSocket</span></code> annotation (a sole-unnamed-param shim warns for one
|
||
cycle). New <code class="docutils literal notranslate"><span class="pre">DependencyError</span></code>/<code class="docutils literal notranslate"><span class="pre">DependencyCycleError</span></code>/<code class="docutils literal notranslate"><span class="pre">DependencyScopeError</span></code>/
|
||
<code class="docutils literal notranslate"><span class="pre">DependencyResolutionError</span></code> exceptions; <code class="docutils literal notranslate"><span class="pre">req</span></code>/<code class="docutils literal notranslate"><span class="pre">request</span></code>/<code class="docutils literal notranslate"><span class="pre">resp</span></code>/<code class="docutils literal notranslate"><span class="pre">response</span></code>/
|
||
<code class="docutils literal notranslate"><span class="pre">ws</span></code>/<code class="docutils literal notranslate"><span class="pre">websocket</span></code> are reserved dependency names.</p></li>
|
||
<li><p><strong>Async-native backends.</strong> Session and rate-limit backends may now expose
|
||
async methods (<code class="docutils literal notranslate"><span class="pre">aget</span></code>/<code class="docutils literal notranslate"><span class="pre">aset</span></code>/<code class="docutils literal notranslate"><span class="pre">adelete</span></code>/<code class="docutils literal notranslate"><span class="pre">atouch</span></code>, <code class="docutils literal notranslate"><span class="pre">ahit</span></code>) that are awaited
|
||
directly instead of run in a thread — with <code class="docutils literal notranslate"><span class="pre">AsyncRedisSessionBackend</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">AsyncRedisBackend</span></code> built in (<code class="docutils literal notranslate"><span class="pre">redis.asyncio</span></code>). <code class="docutils literal notranslate"><span class="pre">RateLimiter.acheck()</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">.install()</span></code> work with any backend. Backend <code class="docutils literal notranslate"><span class="pre">Protocol</span></code>s are exported for
|
||
typing.</p></li>
|
||
<li><p><strong>Sliding server-side session TTL via <code class="docutils literal notranslate"><span class="pre">touch</span></code>.</strong> An unchanged read-only
|
||
request now refreshes the backend TTL with <code class="docutils literal notranslate"><span class="pre">touch</span></code>/<code class="docutils literal notranslate"><span class="pre">atouch</span></code> (no full
|
||
re-serialize) while a mutation still does a full <code class="docutils literal notranslate"><span class="pre">set</span></code> — fixing the
|
||
premature-logout/dirty-tracking trade-off correctly.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">api.add_exception_handler(exc_or_status,</span> <span class="pre">handler)</span></code></strong> registers an error
|
||
handler programmatically (the <code class="docutils literal notranslate"><span class="pre">@api.exception_handler</span></code> decorator now delegates
|
||
to it). A handler for <code class="docutils literal notranslate"><span class="pre">500</span></code>/<code class="docutils literal notranslate"><span class="pre">Exception</span></code> installs the catch-all server-error
|
||
handler.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">api.add_middleware()</span></code> now works after construction</strong> — middleware is
|
||
collected and the stack is built lazily on first request.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id80">
|
||
<h3>Security<a class="headerlink" href="#id80" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Secure-by-default sessions.</strong> The session signing key no longer defaults to
|
||
the public <code class="docutils literal notranslate"><span class="pre">"NOTASECRET"</span></code>. With <code class="docutils literal notranslate"><span class="pre">sessions="auto"</span></code> (the default) Responder uses
|
||
your <code class="docutils literal notranslate"><span class="pre">secret_key</span></code> / <code class="docutils literal notranslate"><span class="pre">RESPONDER_SECRET_KEY</span></code>, else mints a random per-process key
|
||
with a loud warning (set a key for stable, multi-worker sessions).
|
||
<code class="docutils literal notranslate"><span class="pre">secret_key="NOTASECRET"</span></code> now raises. Session cookies are <code class="docutils literal notranslate"><span class="pre">Secure</span></code> by default
|
||
in production (<code class="docutils literal notranslate"><span class="pre">session_https_only=None</span></code>), and <code class="docutils literal notranslate"><span class="pre">SameSite=None</span></code> without Secure
|
||
is rejected.</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">sessions=</span></code> and <code class="docutils literal notranslate"><span class="pre">session_max_age=</span></code> knobs.</strong> <code class="docutils literal notranslate"><span class="pre">sessions=True</span></code> requires a real
|
||
key (raises otherwise); <code class="docutils literal notranslate"><span class="pre">sessions=False</span></code> disables session middleware entirely
|
||
and makes <code class="docutils literal notranslate"><span class="pre">req.session</span></code>/<code class="docutils literal notranslate"><span class="pre">resp.session</span></code> raise a guiding <code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id81">
|
||
<h3>Changed<a class="headerlink" href="#id81" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.session</span></code> is now a property that delegates to <code class="docutils literal notranslate"><span class="pre">req.session</span></code> (so
|
||
<code class="docutils literal notranslate"><span class="pre">resp.session</span> <span class="pre">=</span> <span class="pre">{...}</span></code> actually writes through to the cookie). Reading either
|
||
with sessions disabled raises <code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code>.</p></li>
|
||
<li><p><strong>Deferred middleware stack.</strong> The ASGI stack is assembled lazily with
|
||
<code class="docutils literal notranslate"><span class="pre">ServerErrorMiddleware</span></code> as the outermost application layer (so it catches
|
||
errors from <em>any</em> middleware — sessions, CORS, user middleware) while the
|
||
logging/request-id tier wraps even it, so <code class="docutils literal notranslate"><span class="pre">X-Request-ID</span></code> and the real status
|
||
now appear on <code class="docutils literal notranslate"><span class="pre">500</span></code> responses. <code class="docutils literal notranslate"><span class="pre">API.app</span></code> is a lazy read-only property; mutate
|
||
the stack via <code class="docutils literal notranslate"><span class="pre">add_middleware()</span></code> or wrap the API object for a truly-outermost
|
||
layer. User middleware now sits inside <code class="docutils literal notranslate"><span class="pre">ServerErrorMiddleware</span></code> (its errors are
|
||
caught), and sessions sit below it (a write is not persisted on an unhandled
|
||
<code class="docutils literal notranslate"><span class="pre">500</span></code>).</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">req.method</span></code> is now UPPERCASE</strong> (<code class="docutils literal notranslate"><span class="pre">"GET"</span></code> not <code class="docutils literal notranslate"><span class="pre">"get"</span></code>), matching
|
||
Flask/FastAPI/Starlette/stdlib. For one deprecation cycle it returns an
|
||
<code class="docutils literal notranslate"><span class="pre">HTTPMethod</span></code> (a <code class="docutils literal notranslate"><span class="pre">str</span></code> subclass) that still compares case-insensitively — so
|
||
<code class="docutils literal notranslate"><span class="pre">req.method</span> <span class="pre">==</span> <span class="pre">"get"</span></code> keeps working but emits a <code class="docutils literal notranslate"><span class="pre">DeprecationWarning</span></code>. Hash-
|
||
based membership (<code class="docutils literal notranslate"><span class="pre">req.method</span> <span class="pre">in</span> <span class="pre">{"get"}</span></code>) is case-sensitive and misses; use
|
||
<code class="docutils literal notranslate"><span class="pre">==</span></code>, a tuple/list, or uppercase keys. Removed in Responder 6.0.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v4-1-0-2026-06-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v4.0.0..v4.1.0">v4.1.0</a> - 2026-06-28<a class="headerlink" href="#v4-1-0-2026-06-28" title="Link to this heading">¶</a></h2>
|
||
<p>A backward-compatible quality release: verified correctness and
|
||
resource-safety fixes, additive security hardening, and developer-experience
|
||
improvements. No existing call signatures change.</p>
|
||
<section id="id82">
|
||
<h3>Added<a class="headerlink" href="#id82" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">responder.types</span></code></strong>: public <code class="docutils literal notranslate"><span class="pre">Handler</span></code>, <code class="docutils literal notranslate"><span class="pre">Hook</span></code>, and <code class="docutils literal notranslate"><span class="pre">Dependency</span></code> type
|
||
aliases for annotating your own handlers and hooks.</p></li>
|
||
<li><p>The <code class="docutils literal notranslate"><span class="pre">req</span></code>/<code class="docutils literal notranslate"><span class="pre">resp</span></code> hot surface (<code class="docutils literal notranslate"><span class="pre">headers</span></code>, <code class="docutils literal notranslate"><span class="pre">params</span></code>, <code class="docutils literal notranslate"><span class="pre">method</span></code>, <code class="docutils literal notranslate"><span class="pre">cookies</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">mimetype</span></code>, <code class="docutils literal notranslate"><span class="pre">is_json</span></code>, <code class="docutils literal notranslate"><span class="pre">is_secure</span></code>, …) and the dynamic <code class="docutils literal notranslate"><span class="pre">status_codes</span></code>
|
||
constants are now statically typed, so the shipped <code class="docutils literal notranslate"><span class="pre">py.typed</span></code> marker actually
|
||
helps downstream type checkers (and removes internal <code class="docutils literal notranslate"><span class="pre">type:</span> <span class="pre">ignore</span></code>s).</p></li>
|
||
<li><p><strong>Type-hint-driven body injection</strong>: a handler parameter annotated with a
|
||
Pydantic model now receives the validated request body —
|
||
<code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span> <span class="pre">create(req,</span> <span class="pre">resp,</span> <span class="pre">*,</span> <span class="pre">item:</span> <span class="pre">ItemIn)</span></code> — returning <code class="docutils literal notranslate"><span class="pre">422</span></code> on invalid
|
||
input. Works for sync and async handlers and coexists with path parameters
|
||
and dependencies. (Previously such a signature raised a <code class="docutils literal notranslate"><span class="pre">500</span></code>.) Use an
|
||
explicit <code class="docutils literal notranslate"><span class="pre">response_model=</span></code> for response validation.</p></li>
|
||
<li><p><strong>First-class Pydantic models</strong>: <code class="docutils literal notranslate"><span class="pre">resp.media</span> <span class="pre">=</span> <span class="pre">model</span></code> and <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">Model()</span></code>
|
||
now serialize correctly (across JSON, YAML, and MessagePack), as do
|
||
dataclasses. The JSON encoder also handles <code class="docutils literal notranslate"><span class="pre">datetime</span></code>, <code class="docutils literal notranslate"><span class="pre">date</span></code>, <code class="docutils literal notranslate"><span class="pre">time</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">UUID</span></code>, <code class="docutils literal notranslate"><span class="pre">Decimal</span></code>, <code class="docutils literal notranslate"><span class="pre">set</span></code>, and <code class="docutils literal notranslate"><span class="pre">bytes</span></code> natively — <code class="docutils literal notranslate"><span class="pre">resp.media</span> <span class="pre">=</span> <span class="pre">{"created_at":</span> <span class="pre">datetime.now()}</span></code> no longer 500s.</p></li>
|
||
<li><p><strong>Pluggable type encoder</strong>: <code class="docutils literal notranslate"><span class="pre">API(encoder=...)</span></code> accepts an <code class="docutils literal notranslate"><span class="pre">obj</span> <span class="pre">-></span> <span class="pre">serializable</span></code> callable applied across <strong>all</strong> response formats (JSON, YAML,
|
||
MessagePack) to serialize custom types. It’s tried first and falls back to
|
||
the built-in conversions.</p></li>
|
||
<li><p><strong>Flask-style tuple returns</strong>: a handler may <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">body,</span> <span class="pre">status</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">body,</span> <span class="pre">status,</span> <span class="pre">headers</span></code> (previously these were silently dropped).</p></li>
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">responder.abort(status_code,</span> <span class="pre">*,</span> <span class="pre">detail=None,</span> <span class="pre">headers=None)</span></code></strong> raises a
|
||
rendered HTTP error from anywhere in a handler or dependency, without
|
||
importing Starlette.</p></li>
|
||
<li><p><strong>Bare lifecycle decorators</strong>: <code class="docutils literal notranslate"><span class="pre">@api.before_request</span></code> and <code class="docutils literal notranslate"><span class="pre">@api.after_request</span></code>
|
||
now work without the parentheses, alongside the existing called forms.</p></li>
|
||
<li><p><strong>Sync body access</strong>: <code class="docutils literal notranslate"><span class="pre">req.media_sync()</span></code> and <code class="docutils literal notranslate"><span class="pre">req.text_sync</span></code> let synchronous
|
||
handlers read the request body (they bridge to the loop from the worker
|
||
thread Responder already runs sync handlers in).</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id83">
|
||
<h3>Changed<a class="headerlink" href="#id83" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong><code class="docutils literal notranslate"><span class="pre">response_model</span></code> now fails closed instead of leaking.</strong> Previously a
|
||
response whose data didn’t satisfy its declared <code class="docutils literal notranslate"><span class="pre">response_model</span></code> was sent
|
||
through <em>unvalidated</em> (wrong types, undeclared fields and all). It now
|
||
coerces and strips as documented, and on a genuine validation failure raises
|
||
in debug mode or returns a <code class="docutils literal notranslate"><span class="pre">500</span></code> (never the unvalidated payload) in
|
||
production. Valid responses are unaffected; <code class="docutils literal notranslate"><span class="pre">datetime</span></code>/<code class="docutils literal notranslate"><span class="pre">UUID</span></code>/etc. fields now
|
||
serialize instead of 500-ing. List responses are validated item-by-item.</p></li>
|
||
<li><p>Malformed request bodies now return <strong>400</strong> instead of <strong>500</strong>: invalid
|
||
JSON, YAML, or MessagePack raise a rendered <code class="docutils literal notranslate"><span class="pre">400</span></code>, and binary parts in a
|
||
<code class="docutils literal notranslate"><span class="pre">req.media("form")</span></code> call are skipped rather than crashing.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API(auto_escape=...)</span></code> is now actually forwarded to the template environment
|
||
(it was previously ignored).</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.ok</span></code> reads as <code class="docutils literal notranslate"><span class="pre">200</span></code>-based success until a status code is set, instead of
|
||
raising.</p></li>
|
||
<li><p>Per-request overhead trimmed: coroutine-function detection for views and
|
||
hooks is memoized, and <code class="docutils literal notranslate"><span class="pre">req.params</span></code> reads the raw query string from the ASGI
|
||
scope instead of rebuilding and re-parsing the full URL.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id84">
|
||
<h3>Fixed<a class="headerlink" href="#id84" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Mounted-app routing</strong>: a mount prefix now only matches on a path-segment
|
||
boundary, so e.g. <code class="docutils literal notranslate"><span class="pre">GET</span> <span class="pre">/subscribe</span></code> is no longer mis-routed into an app
|
||
mounted at <code class="docutils literal notranslate"><span class="pre">/sub</span></code> (and sub-paths keep their leading slash). More specific
|
||
(longer) mount prefixes resolve first.</p></li>
|
||
<li><p><strong>Dependency teardown leaks</strong>: a failing generator-dependency teardown no
|
||
longer skips the remaining teardowns — each runs best-effort and failures
|
||
are logged, so connections/files/locks are always released. Applies to HTTP
|
||
routes, WebSocket routes, and app-scoped shutdown.</p></li>
|
||
<li><p><strong>Event-loop blocking</strong>: server-side session backends (e.g. Redis) now run
|
||
their <code class="docutils literal notranslate"><span class="pre">get</span></code>/<code class="docutils literal notranslate"><span class="pre">set</span></code>/<code class="docutils literal notranslate"><span class="pre">delete</span></code> off the event loop, <code class="docutils literal notranslate"><span class="pre">resp.file()</span></code> reads file
|
||
bytes in a worker thread, and the static <code class="docutils literal notranslate"><span class="pre">index.html</span></code> fallback reads off the
|
||
loop too — so these no longer stall the server from <code class="docutils literal notranslate"><span class="pre">async</span></code> handlers.</p></li>
|
||
<li><p><strong>Request-size enforcement</strong>: <code class="docutils literal notranslate"><span class="pre">max_request_size</span></code> is now enforced while the
|
||
body streams in (chunked or lying <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code>) instead of buffering the
|
||
whole body first; also fixes an empty-body re-read.</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">BackgroundQueue.__call__</span></code> no longer wraps work in a pointless
|
||
create-task-then-await; its await-to-completion semantics are now documented
|
||
(use <code class="docutils literal notranslate"><span class="pre">.task</span></code>/<code class="docutils literal notranslate"><span class="pre">.run</span></code> for fire-and-forget).</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id85">
|
||
<h3>Security<a class="headerlink" href="#id85" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Default secret key warning</strong>: Responder now logs a loud warning when cookie
|
||
sessions are signed with the built-in <code class="docutils literal notranslate"><span class="pre">"NOTASECRET"</span></code> default key (outside
|
||
debug mode) — forged session data is otherwise trivial. Set
|
||
<code class="docutils literal notranslate"><span class="pre">API(secret_key=...)</span></code>.</p></li>
|
||
<li><p><strong>Session fixation defense</strong>: server-side sessions mint a fresh id when a
|
||
presented cookie doesn’t resolve, and a new <code class="docutils literal notranslate"><span class="pre">regenerate_session(req)</span></code> helper
|
||
(<code class="docutils literal notranslate"><span class="pre">responder.ext.sessions</span></code>) rotates the id after login/privilege change.</p></li>
|
||
<li><p><strong>Session cookie controls</strong>: <code class="docutils literal notranslate"><span class="pre">API(session_cookie=...,</span> <span class="pre">session_https_only=...,</span> <span class="pre">session_same_site=...)</span></code> configure the session cookie for both cookie-payload
|
||
and server-side sessions.</p></li>
|
||
<li><p><strong>GraphQL hardening</strong>: <code class="docutils literal notranslate"><span class="pre">api.graphql(...,</span> <span class="pre">graphiql=...,</span> <span class="pre">introspection=...,</span> <span class="pre">max_depth=...)</span></code> can disable the in-browser IDE, reject schema-introspection
|
||
queries, and cap query nesting depth (a DoS guard) for production.</p></li>
|
||
<li><p><strong>Path-traversal jail</strong>: <code class="docutils literal notranslate"><span class="pre">resp.file(path,</span> <span class="pre">root=...)</span></code>, <code class="docutils literal notranslate"><span class="pre">resp.stream_file(...,</span> <span class="pre">root=...)</span></code>, and <code class="docutils literal notranslate"><span class="pre">resp.download(...,</span> <span class="pre">root=...)</span></code> resolve <code class="docutils literal notranslate"><span class="pre">path</span></code> under <code class="docutils literal notranslate"><span class="pre">root</span></code> and
|
||
return <code class="docutils literal notranslate"><span class="pre">404</span></code> on any <code class="docutils literal notranslate"><span class="pre">..</span></code>/symlink escape — use whenever the path is user input.</p></li>
|
||
<li><p><strong>Open-redirect guard</strong>: <code class="docutils literal notranslate"><span class="pre">resp.redirect(location,</span> <span class="pre">allow_external=False)</span></code> (and
|
||
<code class="docutils literal notranslate"><span class="pre">api.redirect(...)</span></code>) refuse to redirect to an absolute or protocol-relative
|
||
URL — use for user-supplied locations.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v4-0-0-2026-06-12">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.12.0..v4.0.0">v4.0.0</a> - 2026-06-12<a class="headerlink" href="#v4-0-0-2026-06-12" title="Link to this heading">¶</a></h2>
|
||
<section id="id86">
|
||
<h3>Changed<a class="headerlink" href="#id86" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><strong>Breaking:</strong> Slimmed the default install from ~60 packages to ~30 by
|
||
moving heavy dependencies behind extras:</p>
|
||
<ul>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">pueblo[sfa-full]</span></code> (which pulls in <code class="docutils literal notranslate"><span class="pre">s3fs</span></code>, <code class="docutils literal notranslate"><span class="pre">aiobotocore</span></code>, <code class="docutils literal notranslate"><span class="pre">aiohttp</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">libarchive-c</span></code>, and friends) is now the <code class="docutils literal notranslate"><span class="pre">cli</span></code> extra. <code class="docutils literal notranslate"><span class="pre">responder</span> <span class="pre">run</span></code>
|
||
still works out of the box for local modules and file paths
|
||
(<code class="docutils literal notranslate"><span class="pre">app:api</span></code>, <code class="docutils literal notranslate"><span class="pre">myapp/core.py</span></code>); only remote targets (URLs, <code class="docutils literal notranslate"><span class="pre">github://</span></code>,
|
||
cloud storage) need <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">'responder[cli]'</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">graphene</span></code> and <code class="docutils literal notranslate"><span class="pre">graphql-core</span></code> are now the <code class="docutils literal notranslate"><span class="pre">graphql</span></code> extra. Install
|
||
with <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">'responder[graphql]'</span></code> to use <code class="docutils literal notranslate"><span class="pre">api.graphql()</span></code></p></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-12-0-2026-06-12">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.11.0..v3.12.0">v3.12.0</a> - 2026-06-12<a class="headerlink" href="#v3-12-0-2026-06-12" title="Link to this heading">¶</a></h2>
|
||
<section id="id87">
|
||
<h3>Added<a class="headerlink" href="#id87" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Built-in metrics: <code class="docutils literal notranslate"><span class="pre">API(metrics_route="/metrics")</span></code> serves request counts
|
||
and latency histograms in Prometheus text format, zero dependencies.
|
||
Labels use route patterns (<code class="docutils literal notranslate"><span class="pre">/users/{id}</span></code>) so cardinality stays bounded;
|
||
error responses are recorded with their real status codes</p></li>
|
||
<li><p>Server-side sessions: <code class="docutils literal notranslate"><span class="pre">API(session_backend=...)</span></code> stores session data in
|
||
a backend (<code class="docutils literal notranslate"><span class="pre">MemorySessionBackend</span></code>, <code class="docutils literal notranslate"><span class="pre">RedisSessionBackend</span></code>, or any object
|
||
with <code class="docutils literal notranslate"><span class="pre">get</span></code>/<code class="docutils literal notranslate"><span class="pre">set</span></code>/<code class="docutils literal notranslate"><span class="pre">delete</span></code>) with only an opaque ID in the cookie —
|
||
enabling revocation and unbounded session size. Handler code is unchanged</p></li>
|
||
<li><p>Query-parameter validation: <code class="docutils literal notranslate"><span class="pre">@api.route(...,</span> <span class="pre">params_model=Model)</span></code>
|
||
coerces and validates query strings with Pydantic (<code class="docutils literal notranslate"><span class="pre">422</span></code> on failure),
|
||
exposes the instance as <code class="docutils literal notranslate"><span class="pre">req.state.validated_params</span></code>, maps repeated keys
|
||
to <code class="docutils literal notranslate"><span class="pre">list</span></code> fields, and documents the parameters in the OpenAPI spec</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.render(template,</span> <span class="pre">**context)</span></code> — render a Jinja2 template as the
|
||
HTML response body in one call</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-11-0-2026-06-11">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.10.0..v3.11.0">v3.11.0</a> - 2026-06-11<a class="headerlink" href="#v3-11-0-2026-06-11" title="Link to this heading">¶</a></h2>
|
||
<section id="id88">
|
||
<h3>Added<a class="headerlink" href="#id88" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>HTTP range requests: <code class="docutils literal notranslate"><span class="pre">resp.file()</span></code> and <code class="docutils literal notranslate"><span class="pre">resp.stream_file()</span></code> answer
|
||
<code class="docutils literal notranslate"><span class="pre">Range:</span> <span class="pre">bytes=...</span></code> with <code class="docutils literal notranslate"><span class="pre">206</span> <span class="pre">Partial</span> <span class="pre">Content</span></code> (suffix and open-ended
|
||
ranges, <code class="docutils literal notranslate"><span class="pre">416</span></code> for unsatisfiable, <code class="docutils literal notranslate"><span class="pre">Accept-Ranges</span></code> advertised) — enables
|
||
video seeking and resumable downloads</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.download(path,</span> <span class="pre">filename=...)</span></code> serves files as attachments with
|
||
proper <code class="docutils literal notranslate"><span class="pre">Content-Disposition</span></code> (RFC 5987 encoding for non-ASCII names),
|
||
streamed and resumable</p></li>
|
||
<li><p>Request timeouts: <code class="docutils literal notranslate"><span class="pre">API(request_timeout=seconds)</span></code> answers overrunning
|
||
handlers with <code class="docutils literal notranslate"><span class="pre">504</span> <span class="pre">Gateway</span> <span class="pre">Timeout</span></code> (content-negotiated); dependency
|
||
teardowns still run</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="performance">
|
||
<h3>Performance<a class="headerlink" href="#performance" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Route resolution is cached per (method, path) with invalidation on
|
||
registration — ~10% faster dispatch at 81 routes, growing with route
|
||
count</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-10-0-2026-06-11">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.9.1..v3.10.0">v3.10.0</a> - 2026-06-11<a class="headerlink" href="#v3-10-0-2026-06-11" title="Link to this heading">¶</a></h2>
|
||
<section id="id89">
|
||
<h3>Added<a class="headerlink" href="#id89" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Trailing-slash redirects: requests that miss only by a trailing slash get
|
||
a <code class="docutils literal notranslate"><span class="pre">307</span></code> to the canonical path, preserving method and query string.
|
||
Disable with <code class="docutils literal notranslate"><span class="pre">API(redirect_slashes=False)</span></code></p></li>
|
||
<li><p>Request size limits: <code class="docutils literal notranslate"><span class="pre">API(max_request_size=bytes)</span></code> returns <code class="docutils literal notranslate"><span class="pre">413</span></code> for
|
||
oversized bodies — fast-fails on <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> and enforces
|
||
cumulatively for chunked/streamed uploads</p></li>
|
||
<li><p>Automatic ETags: <code class="docutils literal notranslate"><span class="pre">API(auto_etag=True)</span></code> adds a content-hash <code class="docutils literal notranslate"><span class="pre">ETag</span></code> to GET
|
||
responses with full <code class="docutils literal notranslate"><span class="pre">304</span> <span class="pre">Not</span> <span class="pre">Modified</span></code> handling; an explicit <code class="docutils literal notranslate"><span class="pre">resp.etag</span></code>
|
||
always wins</p></li>
|
||
<li><p>After-response background tasks: <code class="docutils literal notranslate"><span class="pre">resp.background(func,</span> <span class="pre">*args)</span></code> defers
|
||
work until the client has the response (sync and async, ordered)</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.cache_control(...)</span></code> helper for building <code class="docutils literal notranslate"><span class="pre">Cache-Control</span></code> headers</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id90">
|
||
<h3>Fixed<a class="headerlink" href="#id90" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>A <code class="docutils literal notranslate"><span class="pre">413</span></code> raised while reading the body during <code class="docutils literal notranslate"><span class="pre">request_model</span></code> validation
|
||
is no longer swallowed into a <code class="docutils literal notranslate"><span class="pre">422</span></code></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id91">
|
||
<h3>Changed<a class="headerlink" href="#id91" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Trailing-slash redirects are on by default (previously such requests
|
||
were 404s)</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-9-1-2026-06-11">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.9.0..v3.9.1">v3.9.1</a> - 2026-06-11<a class="headerlink" href="#v3-9-1-2026-06-11" title="Link to this heading">¶</a></h2>
|
||
<section id="id92">
|
||
<h3>Added<a class="headerlink" href="#id92" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Conditional request support: set <code class="docutils literal notranslate"><span class="pre">resp.etag</span></code> or <code class="docutils literal notranslate"><span class="pre">resp.last_modified</span></code> and
|
||
matching <code class="docutils literal notranslate"><span class="pre">If-None-Match</span></code>/<code class="docutils literal notranslate"><span class="pre">If-Modified-Since</span></code> requests automatically get
|
||
<code class="docutils literal notranslate"><span class="pre">304</span> <span class="pre">Not</span> <span class="pre">Modified</span></code> (RFC 7232 semantics: <code class="docutils literal notranslate"><span class="pre">If-None-Match</span></code> precedence, weak
|
||
comparison, GET/HEAD only)</p></li>
|
||
<li><p>Request body streaming: <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">for</span> <span class="pre">chunk</span> <span class="pre">in</span> <span class="pre">req.stream()</span></code> iterates large
|
||
uploads without buffering</p></li>
|
||
<li><p>Pluggable rate-limiter backends: <code class="docutils literal notranslate"><span class="pre">RateLimiter(backend=...)</span></code> with the
|
||
in-memory default plus a new <code class="docutils literal notranslate"><span class="pre">RedisBackend</span></code> for multi-process deployments</p></li>
|
||
<li><p>Application state: <code class="docutils literal notranslate"><span class="pre">api.state</span></code> namespace, reachable from handlers via
|
||
<code class="docutils literal notranslate"><span class="pre">req.api.state</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">req.api</span></code> is now populated with the owning <code class="docutils literal notranslate"><span class="pre">API</span></code> instance (it was always
|
||
<code class="docutils literal notranslate"><span class="pre">None</span></code> before)</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id93">
|
||
<h3>Fixed<a class="headerlink" href="#id93" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">API(static_dir=None)</span></code> crashed on every route registration — the static
|
||
fallback assertion now only applies when no endpoint is given</p></li>
|
||
<li><p>The static-fallback error is a <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> instead of a bare <code class="docutils literal notranslate"><span class="pre">assert</span></code></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id94">
|
||
<h3>Performance<a class="headerlink" href="#id94" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Request headers are parsed into the case-insensitive dict lazily, on
|
||
first access (~5% faster dispatch on header-heavy requests that don’t
|
||
read headers)</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-9-0-2026-06-11">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.8.0..v3.9.0">v3.9.0</a> - 2026-06-11<a class="headerlink" href="#v3-9-0-2026-06-11" title="Link to this heading">¶</a></h2>
|
||
<section id="id95">
|
||
<h3>Added<a class="headerlink" href="#id95" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Dependency injection for WebSocket handlers: declare path parameters and
|
||
registered dependencies by name after the <code class="docutils literal notranslate"><span class="pre">ws</span></code> argument. Request-scoped
|
||
providers taking a parameter receive the WebSocket; generator teardown
|
||
runs when the handler finishes. Handlers that only take <code class="docutils literal notranslate"><span class="pre">ws</span></code> are unaffected</p></li>
|
||
<li><p>OpenAPI 3.1 support (<code class="docutils literal notranslate"><span class="pre">openapi="3.1.0"</span></code>)</p></li>
|
||
<li><p>The OpenAPI schema endpoint now serves JSON when requested via
|
||
<code class="docutils literal notranslate"><span class="pre">Accept:</span> <span class="pre">application/json</span></code>, or always when <code class="docutils literal notranslate"><span class="pre">openapi_route</span></code> ends in <code class="docutils literal notranslate"><span class="pre">.json</span></code></p></li>
|
||
<li><p>Path parameters are documented automatically in the OpenAPI spec from
|
||
route patterns (<code class="docutils literal notranslate"><span class="pre">{id:int}</span></code> → required integer parameter)</p></li>
|
||
<li><p>Built-in error responses (404, 405) are content-negotiated: JSON clients
|
||
receive <code class="docutils literal notranslate"><span class="pre">{"error":</span> <span class="pre">...}</span></code> bodies instead of plain text</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id96">
|
||
<h3>Fixed<a class="headerlink" href="#id96" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>OpenAPI paths no longer leak convertor patterns (<code class="docutils literal notranslate"><span class="pre">/users/{id:int}</span></code> is now
|
||
emitted as the spec-compliant <code class="docutils literal notranslate"><span class="pre">/users/{id}</span></code>)</p></li>
|
||
<li><p>Registering a duplicate route now raises <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> (previously an
|
||
<code class="docutils literal notranslate"><span class="pre">assert</span></code> that disappears under <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-O</span></code>)</p></li>
|
||
<li><p>Removed dead <code class="docutils literal notranslate"><span class="pre">_exception_handlers</span></code> bookkeeping in <code class="docutils literal notranslate"><span class="pre">API.exception_handler</span></code></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id97">
|
||
<h3>Changed<a class="headerlink" href="#id97" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">mypy</span></code> now passes with zero errors across the codebase (was 25); <code class="docutils literal notranslate"><span class="pre">ruff</span></code>
|
||
is clean as well</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">types-pyyaml</span></code> added to the <code class="docutils literal notranslate"><span class="pre">test</span></code> extra</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-8-0-2026-06-11">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.7.0..v3.8.0">v3.8.0</a> - 2026-06-11<a class="headerlink" href="#v3-8-0-2026-06-11" title="Link to this heading">¶</a></h2>
|
||
<section id="id98">
|
||
<h3>Added<a class="headerlink" href="#id98" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Handlers can return values: a <code class="docutils literal notranslate"><span class="pre">dict</span></code>/<code class="docutils literal notranslate"><span class="pre">list</span></code> sets <code class="docutils literal notranslate"><span class="pre">resp.media</span></code>, a <code class="docutils literal notranslate"><span class="pre">str</span></code> sets
|
||
<code class="docutils literal notranslate"><span class="pre">resp.text</span></code>, and <code class="docutils literal notranslate"><span class="pre">bytes</span></code> set <code class="docutils literal notranslate"><span class="pre">resp.content</span></code>. Returning <code class="docutils literal notranslate"><span class="pre">None</span></code> keeps the
|
||
mutate-<code class="docutils literal notranslate"><span class="pre">resp</span></code> behavior, so existing handlers are unaffected</p></li>
|
||
<li><p>App-scoped dependencies: <code class="docutils literal notranslate"><span class="pre">@api.dependency(scope="app")</span></code> resolves the
|
||
provider once on first use and caches it for the application’s lifetime;
|
||
generator teardown runs at shutdown</p></li>
|
||
<li><p>Automatic <code class="docutils literal notranslate"><span class="pre">OPTIONS</span></code> responses with an <code class="docutils literal notranslate"><span class="pre">Allow</span></code> header for method-restricted routes</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">HEAD</span></code> requests are accepted wherever <code class="docutils literal notranslate"><span class="pre">GET</span></code> is</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">set_cookie()</span></code> gains a <code class="docutils literal notranslate"><span class="pre">samesite</span></code> parameter, defaulting to <code class="docutils literal notranslate"><span class="pre">"lax"</span></code></p></li>
|
||
<li><p>The validated <code class="docutils literal notranslate"><span class="pre">request_model</span></code> instance is now available to handlers as
|
||
<code class="docutils literal notranslate"><span class="pre">req.state.validated</span></code> — no need to re-parse the body</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id99">
|
||
<h3>Changed<a class="headerlink" href="#id99" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Requests to an existing path with an unsupported method now return
|
||
<code class="docutils literal notranslate"><span class="pre">405</span> <span class="pre">Method</span> <span class="pre">Not</span> <span class="pre">Allowed</span></code> with an <code class="docutils literal notranslate"><span class="pre">Allow</span></code> header (previously 404)</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">RouteGroup.before_request</span></code> hooks are now scoped to the group’s prefix
|
||
(previously they silently applied to every route)</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id100">
|
||
<h3>Performance<a class="headerlink" href="#id100" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>View signature inspection for dependency injection is cached per function</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-7-0-2026-06-11">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.6.2..v3.7.0">v3.7.0</a> - 2026-06-11<a class="headerlink" href="#v3-7-0-2026-06-11" title="Link to this heading">¶</a></h2>
|
||
<section id="id101">
|
||
<h3>Added<a class="headerlink" href="#id101" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Dependency injection for route handlers: register providers with
|
||
<code class="docutils literal notranslate"><span class="pre">@api.dependency()</span></code> (or <code class="docutils literal notranslate"><span class="pre">api.add_dependency(name,</span> <span class="pre">provider)</span></code>) and declare
|
||
them as view parameters by name. Supports sync/async functions and
|
||
generators (code after <code class="docutils literal notranslate"><span class="pre">yield</span></code> runs as teardown once the response is sent).
|
||
Providers accepting a parameter receive the current <code class="docutils literal notranslate"><span class="pre">Request</span></code>. Dependencies
|
||
resolve at most once per request; path parameters take precedence.</p></li>
|
||
<li><p>Per-route rate limiting via <code class="docutils literal notranslate"><span class="pre">RateLimiter.limit</span></code> decorator</p></li>
|
||
<li><p>WebSocket before-request hooks can now reject connections: closing the
|
||
socket in a hook short-circuits the route handler</p></li>
|
||
<li><p>WebSocket before-request hooks may now be sync functions (run in the threadpool)</p></li>
|
||
<li><p>Custom formats registered on <code class="docutils literal notranslate"><span class="pre">api.formats</span></code> now actually reach request
|
||
parsing and response negotiation (previously each request got a fresh
|
||
default format registry)</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id102">
|
||
<h3>Fixed<a class="headerlink" href="#id102" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">{value:float}</span></code> path convertor matched garbage like <code class="docutils literal notranslate"><span class="pre">1a5</span></code> (unescaped regex
|
||
dot) and crashed with a 500 — now correctly returns 404</p></li>
|
||
<li><p>Literal characters in route paths are now regex-escaped, so <code class="docutils literal notranslate"><span class="pre">/file.json</span></code>
|
||
no longer matches <code class="docutils literal notranslate"><span class="pre">/fileXjson</span></code></p></li>
|
||
<li><p>Unbounded memory growth in <code class="docutils literal notranslate"><span class="pre">BackgroundQueue</span></code> — completed futures are now
|
||
pruned from <code class="docutils literal notranslate"><span class="pre">results</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">req.media("form")</span></code> crashed with a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> when the request had no
|
||
<code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> header</p></li>
|
||
<li><p>Content negotiation returned an empty body for <code class="docutils literal notranslate"><span class="pre">Accept</span></code> headers matching
|
||
encode-incapable formats (e.g. <code class="docutils literal notranslate"><span class="pre">multipart/form-data</span></code>) — now falls through
|
||
to JSON</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id103">
|
||
<h3>Changed<a class="headerlink" href="#id103" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">Request.url</span></code> and <code class="docutils literal notranslate"><span class="pre">Request.params</span></code> are now computed once and cached</p></li>
|
||
<li><p>Format registries are no longer rebuilt twice per request</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-6-2-2026-04-12">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.6.1..v3.6.2">v3.6.2</a> - 2026-04-12<a class="headerlink" href="#v3-6-2-2026-04-12" title="Link to this heading">¶</a></h2>
|
||
<section id="id104">
|
||
<h3>Fixed<a class="headerlink" href="#id104" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>GraphQL error responses now correctly return 400 status instead of always 200</p></li>
|
||
<li><p>OpenAPI docs UI now respects custom <code class="docutils literal notranslate"><span class="pre">openapi_route</span></code> instead of hardcoding <code class="docutils literal notranslate"><span class="pre">/schema.yml</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">before_requests</span></code> default type mismatch that could crash routes called outside the router</p></li>
|
||
<li><p>Blocking synchronous file I/O in <code class="docutils literal notranslate"><span class="pre">Response.stream_file()</span></code> — now uses async I/O via anyio</p></li>
|
||
<li><p>Memory leak in rate limiter (empty bucket keys never cleaned up)</p></li>
|
||
<li><p>Race condition in rate limiter <code class="docutils literal notranslate"><span class="pre">check()</span></code> — added thread-safe locking</p></li>
|
||
<li><p>WSGI fallback catching all <code class="docutils literal notranslate"><span class="pre">TypeError</span></code>s instead of just call-signature mismatches</p></li>
|
||
<li><p>Pydantic request/response model validation crashing on non-dict bodies</p></li>
|
||
<li><p>Test assertions that could never fail (<code class="docutils literal notranslate"><span class="pre">or</span> <span class="pre">True</span></code>, <code class="docutils literal notranslate"><span class="pre"><</span> <span class="pre">500</span></code> patterns)</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">CaseInsensitiveDict</span></code> missing <code class="docutils literal notranslate"><span class="pre">__delitem__</span></code>, <code class="docutils literal notranslate"><span class="pre">pop</span></code>, and <code class="docutils literal notranslate"><span class="pre">setdefault</span></code> overrides</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">assert</span></code> used for input validation in OpenAPI extension (stripped by <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-O</span></code>)</p></li>
|
||
<li><p>Potential XSS in GraphiQL template endpoint injection</p></li>
|
||
<li><p>Dead <code class="docutils literal notranslate"><span class="pre">or</span> <span class="pre">""</span></code> in media format detection logic</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id105">
|
||
<h3>Changed<a class="headerlink" href="#id105" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">DELETE</span></code> requests now participate in Pydantic request body validation</p></li>
|
||
<li><p>Simplified status code category check to use chained comparison</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id106">
|
||
<h3>Removed<a class="headerlink" href="#id106" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Unused <code class="docutils literal notranslate"><span class="pre">method</span></code> parameter from <code class="docutils literal notranslate"><span class="pre">load_target()</span></code></p></li>
|
||
<li><p>Unused Node.js setup step from CI test workflow</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-6-1-2026-04-12">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.6.0..v3.6.1">v3.6.1</a> - 2026-04-12<a class="headerlink" href="#v3-6-1-2026-04-12" title="Link to this heading">¶</a></h2>
|
||
<section id="id107">
|
||
<h3>Added<a class="headerlink" href="#id107" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Configurable GZip compression via <code class="docutils literal notranslate"><span class="pre">gzip</span></code> parameter on <code class="docutils literal notranslate"><span class="pre">API()</span></code> (defaults to <code class="docutils literal notranslate"><span class="pre">True</span></code>)</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-6-0-2026-03-24">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.5.0..v3.6.0">v3.6.0</a> - 2026-03-24<a class="headerlink" href="#v3-6-0-2026-03-24" title="Link to this heading">¶</a></h2>
|
||
<section id="id108">
|
||
<h3>Added<a class="headerlink" href="#id108" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Built-in structured logging with per-request context (<code class="docutils literal notranslate"><span class="pre">enable_logging=True</span></code>)</p>
|
||
<ul>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">api.log</span></code> — always-available logger, enriched with request context when logging is enabled</p></li>
|
||
<li><p>Automatic access logging with timing: <code class="docutils literal notranslate"><span class="pre">GET</span> <span class="pre">/path</span> <span class="pre">→</span> <span class="pre">200</span> <span class="pre">(1.2ms)</span></code></p></li>
|
||
<li><p>Request ID generation/forwarding via <code class="docutils literal notranslate"><span class="pre">X-Request-ID</span></code> header</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">contextvars</span></code>-based request context (ID, method, path, client IP) on every log record</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">responder.ext.logging</span></code> module: <code class="docutils literal notranslate"><span class="pre">get_logger()</span></code>, <code class="docutils literal notranslate"><span class="pre">RequestContext</span></code>, <code class="docutils literal notranslate"><span class="pre">RequestContextFilter</span></code></p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p>CLAUDE.md project guide and <code class="docutils literal notranslate"><span class="pre">/release</span></code> command</p></li>
|
||
<li><p>Version number in docs sidebar</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id109">
|
||
<h3>Changed<a class="headerlink" href="#id109" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Comprehensive documentation improvements across all pages</p>
|
||
<ul>
|
||
<li><p>Deployment: health checks, Docker Compose, Caddy, Procfile, production checklist</p></li>
|
||
<li><p>API reference: usage examples for every class</p></li>
|
||
<li><p>Feature tour: Pydantic validation, content negotiation, structured logging sections</p></li>
|
||
<li><p>Tutorials: modernized SQLAlchemy to <code class="docutils literal notranslate"><span class="pre">mapped_column()</span></code>, fixed deprecated <code class="docutils literal notranslate"><span class="pre">datetime.utcnow()</span></code>,
|
||
WebSocket <code class="docutils literal notranslate"><span class="pre">WebSocketDisconnect</span></code> handling, role-based auth, auth strategy guide</p></li>
|
||
<li><p>Testing: rate limiting and WSGI mount examples</p></li>
|
||
<li><p>Middleware: pure ASGI middleware example</p></li>
|
||
<li><p>Quickstart: links to all tutorials</p></li>
|
||
<li><p>Sandbox: full rewrite with project layout</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p>Docker example uses <code class="docutils literal notranslate"><span class="pre">uv</span></code> instead of pip</p></li>
|
||
<li><p>Backlog updated: removed implemented features, replaced HTTP/2 server push with dependency injection</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id110">
|
||
<h3>Removed<a class="headerlink" href="#id110" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">uv.lock</span></code> — this is a library, not an application</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-5-0-2026-03-24">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.4.0..v3.5.0">v3.5.0</a> - 2026-03-24<a class="headerlink" href="#v3-5-0-2026-03-24" title="Link to this heading">¶</a></h2>
|
||
<section id="id111">
|
||
<h3>Added<a class="headerlink" href="#id111" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>CI validation for Python 3.14, 3.14 free-threaded, and PyPy 3.11</p></li>
|
||
<li><p>Marimo notebook mounting docs and example</p></li>
|
||
<li><p>Type annotations for <code class="docutils literal notranslate"><span class="pre">routes.py</span></code></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id112">
|
||
<h3>Changed<a class="headerlink" href="#id112" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Replaced deprecated <code class="docutils literal notranslate"><span class="pre">asyncio.iscoroutinefunction</span></code> with <code class="docutils literal notranslate"><span class="pre">inspect.iscoroutinefunction</span></code> ahead of Python 3.16 removal</p></li>
|
||
<li><p>Narrowed broad <code class="docutils literal notranslate"><span class="pre">except</span> <span class="pre">Exception</span></code> to specific exceptions in response model serialization and websocket chat example</p></li>
|
||
<li><p>Improved GraphQL API interface with expanded test coverage</p></li>
|
||
<li><p>Code formatting cleanup via pyproject-fmt and ruff</p></li>
|
||
<li><p>Dropped Python 3.9 from CI</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id113">
|
||
<h3>Fixed<a class="headerlink" href="#id113" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>WSGI mount returning 400 when requesting the exact mount root path</p></li>
|
||
<li><p>Werkzeug 3.1.7 compatibility for trusted host validation in tests</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">future.result</span></code> bare property access in background task test (now properly calls <code class="docutils literal notranslate"><span class="pre">future.result()</span></code>)</p></li>
|
||
<li><p>OpenAPI template packaging and static file serving</p></li>
|
||
<li><p>RST title underline warning breaking docs CI</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id114">
|
||
<h3>Removed<a class="headerlink" href="#id114" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Read the Docs configuration (docs hosted on GitHub Pages)</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-4-0-2026-03-22">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.3.0..v3.4.0">v3.4.0</a> - 2026-03-22<a class="headerlink" href="#v3-4-0-2026-03-22" title="Link to this heading">¶</a></h2>
|
||
<section id="id115">
|
||
<h3>Changed<a class="headerlink" href="#id115" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Upgraded to Starlette 1.0</p></li>
|
||
<li><p>Added comprehensive docstrings across the codebase</p></li>
|
||
<li><p>Expanded API reference documentation</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-3-0-2026-03-22">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.2.0..v3.3.0">v3.3.0</a> - 2026-03-22<a class="headerlink" href="#v3-3-0-2026-03-22" title="Link to this heading">¶</a></h2>
|
||
<section id="id116">
|
||
<h3>Added<a class="headerlink" href="#id116" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Full documentation rewrite: tutorials for REST APIs, SQLAlchemy, Flask migration</p></li>
|
||
<li><p>Auth, WebSocket, middleware, and configuration guides</p></li>
|
||
<li><p>Testing docs with prose, examples, and tips</p></li>
|
||
<li><p>GitHub Pages deployment for docs</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id117">
|
||
<h3>Changed<a class="headerlink" href="#id117" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Reworked homepage prose</p></li>
|
||
<li><p>Rewrote CLI and API reference docs</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-2-0-2026-03-22">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v3.0.0..v3.2.0">v3.2.0</a> - 2026-03-22<a class="headerlink" href="#v3-2-0-2026-03-22" title="Link to this heading">¶</a></h2>
|
||
<section id="id118">
|
||
<h3>Added<a class="headerlink" href="#id118" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Pydantic auto-validation: <code class="docutils literal notranslate"><span class="pre">request_model</span></code> validates input, returns 422 on failure</p></li>
|
||
<li><p>Pydantic auto-serialization: <code class="docutils literal notranslate"><span class="pre">response_model</span></code> strips extra fields from responses</p></li>
|
||
<li><p>Server-Sent Events: <code class="docutils literal notranslate"><span class="pre">@resp.sse</span></code> for real-time streaming</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.stream_file()</span></code> for streaming large files without loading into memory</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">@api.after_request()</span></code> hooks</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">api.group("/prefix")</span></code> for route groups and API versioning</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">api.graphql("/path",</span> <span class="pre">schema=schema)</span></code> one-liner GraphQL setup</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">api</span> <span class="pre">=</span> <span class="pre">responder.API(request_id=True)</span></code> for automatic request ID generation</p></li>
|
||
<li><p>Built-in rate limiter: <code class="docutils literal notranslate"><span class="pre">RateLimiter(requests=100,</span> <span class="pre">period=60).install(api)</span></code></p></li>
|
||
<li><p>MessagePack format support: <code class="docutils literal notranslate"><span class="pre">await</span> <span class="pre">req.media("msgpack")</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">req.is_json</span></code>, <code class="docutils literal notranslate"><span class="pre">req.path_params</span></code>, <code class="docutils literal notranslate"><span class="pre">req.client</span></code> properties</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">api.exception_handler()</span></code> decorator for custom error handling</p></li>
|
||
<li><p>Lifespan context manager support</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">uuid</span></code> and <code class="docutils literal notranslate"><span class="pre">path</span></code> route convertors</p></li>
|
||
<li><p>PEP 561 <code class="docutils literal notranslate"><span class="pre">py.typed</span></code> marker</p></li>
|
||
<li><p>Pydantic support for OpenAPI schema generation</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id119">
|
||
<h3>Changed<a class="headerlink" href="#id119" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Dependencies flattened: <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">responder</span></code> gets everything</p></li>
|
||
<li><p>Core deps reduced to starlette + uvicorn</p></li>
|
||
<li><p>TestClient lazy-loaded (no httpx import in production)</p></li>
|
||
<li><p>Before-request hooks can short-circuit by setting status code</p></li>
|
||
<li><p>Removed poethepoet task runner</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id120">
|
||
<h3>Fixed<a class="headerlink" href="#id120" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Multipart parser losing headers when parts have multiple headers</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">url_for()</span></code> with typed route params (<code class="docutils literal notranslate"><span class="pre">{id:int}</span></code>)</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">resp.body</span></code> encoding crash on bytes content</p></li>
|
||
<li><p>GraphQL text query missing <code class="docutils literal notranslate"><span class="pre">await</span></code></p></li>
|
||
<li><p>Streaming responses not sending Content-Type headers</p></li>
|
||
<li><p>Python 3.9 compatibility for union type syntax</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v3-0-0-2026-03-22">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v2.0.5..v3.0.0">v3.0.0</a> - 2026-03-22<a class="headerlink" href="#v3-0-0-2026-03-22" title="Link to this heading">¶</a></h2>
|
||
<section id="id121">
|
||
<h3>Added<a class="headerlink" href="#id121" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Platform: Added support for Python 3.10 - Python 3.13</p></li>
|
||
<li><p>CLI: <code class="docutils literal notranslate"><span class="pre">responder</span> <span class="pre">run</span></code> now also accepts a filesystem path on its <code class="docutils literal notranslate"><span class="pre"><target></span></code>
|
||
argument, enabling usage on single-file applications.</p></li>
|
||
<li><p>CLI: <code class="docutils literal notranslate"><span class="pre">responder</span> <span class="pre">run</span></code> now also accepts URLs.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id122">
|
||
<h3>Changed<a class="headerlink" href="#id122" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Platform: Minimum Python version is now 3.9 (dropped 3.6, 3.7, 3.8)</p></li>
|
||
<li><p>Dependencies: Dramatically reduced core dependency count (10 → 5)</p>
|
||
<ul>
|
||
<li><p>Removed <code class="docutils literal notranslate"><span class="pre">requests</span></code>, <code class="docutils literal notranslate"><span class="pre">requests-toolbelt</span></code>, <code class="docutils literal notranslate"><span class="pre">rfc3986</span></code>, <code class="docutils literal notranslate"><span class="pre">whitenoise</span></code></p></li>
|
||
<li><p>Moved <code class="docutils literal notranslate"><span class="pre">apispec</span></code> and <code class="docutils literal notranslate"><span class="pre">marshmallow</span></code> to <code class="docutils literal notranslate"><span class="pre">openapi</span></code> optional extra</p></li>
|
||
<li><p>Replaced <code class="docutils literal notranslate"><span class="pre">rfc3986</span></code> with stdlib <code class="docutils literal notranslate"><span class="pre">urllib.parse</span></code></p></li>
|
||
<li><p>Replaced <code class="docutils literal notranslate"><span class="pre">requests-toolbelt</span></code> multipart decoder with <code class="docutils literal notranslate"><span class="pre">python-multipart</span></code></p></li>
|
||
<li><p>Replaced deprecated <code class="docutils literal notranslate"><span class="pre">starlette.middleware.wsgi</span></code> with <code class="docutils literal notranslate"><span class="pre">a2wsgi</span></code></p></li>
|
||
<li><p>Switched from WhiteNoise to ServeStatic</p></li>
|
||
</ul>
|
||
</li>
|
||
<li><p>Dependencies: Pinned <code class="docutils literal notranslate"><span class="pre">starlette[full]>=0.40</span></code> (was unpinned)</p></li>
|
||
<li><p>GraphQL: Upgraded to <code class="docutils literal notranslate"><span class="pre">graphene>=3</span></code> and <code class="docutils literal notranslate"><span class="pre">graphql-core>=3.1</span></code>
|
||
(from <code class="docutils literal notranslate"><span class="pre">graphene<3</span></code> and <code class="docutils literal notranslate"><span class="pre">graphql-server-core</span></code>, which is unmaintained)</p></li>
|
||
<li><p>GraphQL: Updated GraphiQL UI from 0.12.0 (2018) to 3.0.6 with React 18</p></li>
|
||
<li><p>Extensions: All of CLI-, GraphQL-, and OpenAPI-Support modules are
|
||
extensions now, found within the <code class="docutils literal notranslate"><span class="pre">responder.ext</span></code> module namespace.</p></li>
|
||
<li><p>Packaging: Migrated from <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> to declarative <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id123">
|
||
<h3>Removed<a class="headerlink" href="#id123" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Platform: Removed support for EOL Python 3.6, 3.7, 3.8</p></li>
|
||
<li><p>Status codes: Removed deprecated <code class="docutils literal notranslate"><span class="pre">resume_incomplete</span></code> and <code class="docutils literal notranslate"><span class="pre">resume</span></code>
|
||
aliases for HTTP 308 (marked for removal in 3.0)</p></li>
|
||
<li><p>CLI: <code class="docutils literal notranslate"><span class="pre">responder</span> <span class="pre">run</span> <span class="pre">--build</span></code> ceased to exist</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id124">
|
||
<h3>Fixed<a class="headerlink" href="#id124" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Routing: Fixed dispatching <code class="docutils literal notranslate"><span class="pre">static_route=None</span></code> on Windows</p></li>
|
||
<li><p>uvicorn: <code class="docutils literal notranslate"><span class="pre">--debug</span></code> now maps to uvicorn’s <code class="docutils literal notranslate"><span class="pre">log_level</span> <span class="pre">=</span> <span class="pre">"debug"</span></code></p></li>
|
||
<li><p>Tests: Fixed deprecated httpx TestClient usage</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v2-0-5-2019-12-15">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v2.0.4..v2.0.5">v2.0.5</a> - 2019-12-15<a class="headerlink" href="#v2-0-5-2019-12-15" title="Link to this heading">¶</a></h2>
|
||
<section id="id125">
|
||
<h3>Added<a class="headerlink" href="#id125" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Update requirements to support python 3.8</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v2-0-4-2019-11-19">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v2.0.3..v2.0.4">v2.0.4</a> - 2019-11-19<a class="headerlink" href="#v2-0-4-2019-11-19" title="Link to this heading">¶</a></h2>
|
||
<section id="id126">
|
||
<h3>Fixed<a class="headerlink" href="#id126" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Fix static app resolving</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v2-0-3-2019-09-20">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v2.0.2..v2.0.3">v2.0.3</a> - 2019-09-20<a class="headerlink" href="#v2-0-3-2019-09-20" title="Link to this heading">¶</a></h2>
|
||
<section id="id127">
|
||
<h3>Fixed<a class="headerlink" href="#id127" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Fix template conflicts</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v2-0-2-2019-09-20">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v2.0.1..v2.0.2">v2.0.2</a> - 2019-09-20<a class="headerlink" href="#v2-0-2-2019-09-20" title="Link to this heading">¶</a></h2>
|
||
<section id="id128">
|
||
<h3>Fixed<a class="headerlink" href="#id128" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Fix template conflicts</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v2-0-1-2019-09-20">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v2.0.0..v2.0.1">v2.0.1</a> - 2019-09-20<a class="headerlink" href="#v2-0-1-2019-09-20" title="Link to this heading">¶</a></h2>
|
||
<section id="id129">
|
||
<h3>Fixed<a class="headerlink" href="#id129" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Fix template import</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v2-0-0-2019-09-19">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.3.2..v2.0.0">v2.0.0</a> - 2019-09-19<a class="headerlink" href="#v2-0-0-2019-09-19" title="Link to this heading">¶</a></h2>
|
||
<section id="id130">
|
||
<h3>Changed<a class="headerlink" href="#id130" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Refactor Router and Schema</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-3-2-2019-08-15">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.3.1..v1.3.2">v1.3.2</a> - 2019-08-15<a class="headerlink" href="#v1-3-2-2019-08-15" title="Link to this heading">¶</a></h2>
|
||
<section id="id131">
|
||
<h3>Added<a class="headerlink" href="#id131" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>ASGI 3 support</p></li>
|
||
<li><p>CI tests for python 3.8-dev</p></li>
|
||
<li><p>Now requests have <code class="docutils literal notranslate"><span class="pre">state</span></code> a mapping object</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id132">
|
||
<h3>Deprecated<a class="headerlink" href="#id132" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>ASGI 2</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-3-1-2019-04-28">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.3.0..v1.3.1">v1.3.1</a> - 2019-04-28<a class="headerlink" href="#v1-3-1-2019-04-28" title="Link to this heading">¶</a></h2>
|
||
<section id="id133">
|
||
<h3>Added<a class="headerlink" href="#id133" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Route params Converters</p></li>
|
||
<li><p>Add search for documentation pages</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id134">
|
||
<h3>Changed<a class="headerlink" href="#id134" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Bump dependencies</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-3-0-2019-02-22">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.2.0..v1.3.0">v1.3.0</a> - 2019-02-22<a class="headerlink" href="#v1-3-0-2019-02-22" title="Link to this heading">¶</a></h2>
|
||
<section id="id135">
|
||
<h3>Fixed<a class="headerlink" href="#id135" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Versioning issue</p></li>
|
||
<li><p>Multiple cookies.</p></li>
|
||
<li><p>Whitenoise returns not found.</p></li>
|
||
<li><p>Other bugfixes.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id136">
|
||
<h3>Added<a class="headerlink" href="#id136" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Stream support via <code class="docutils literal notranslate"><span class="pre">resp.stream</span></code>.</p></li>
|
||
<li><p>Cookie directives via <code class="docutils literal notranslate"><span class="pre">resp.set_cookie</span></code>.</p></li>
|
||
<li><p>Add <code class="docutils literal notranslate"><span class="pre">resp.html</span></code> to send HTML.</p></li>
|
||
<li><p>Other improvements.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-1-3-2019-01-12">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.1.2..v1.1.3">v1.1.3</a> - 2019-01-12<a class="headerlink" href="#v1-1-3-2019-01-12" title="Link to this heading">¶</a></h2>
|
||
<section id="id137">
|
||
<h3>Changed<a class="headerlink" href="#id137" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Refactor <code class="docutils literal notranslate"><span class="pre">_route_for</span></code></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id138">
|
||
<h3>Fixed<a class="headerlink" href="#id138" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Resolve startup/shutdwown events</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-2-0-2018-12-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.1.3..v1.2.0">v1.2.0</a> - 2018-12-29<a class="headerlink" href="#v1-2-0-2018-12-29" title="Link to this heading">¶</a></h2>
|
||
<section id="id139">
|
||
<h3>Added<a class="headerlink" href="#id139" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Documentations</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id140">
|
||
<h3>Changed<a class="headerlink" href="#id140" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Use Starlette’s LifeSpan middleware</p></li>
|
||
<li><p>Update denpendencies</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id141">
|
||
<h3>Fixed<a class="headerlink" href="#id141" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Fix route.is_class_based</p></li>
|
||
<li><p>Fix test_500</p></li>
|
||
<li><p>Typos</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-1-2-2018-11-11">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.1.1..v1.1.2">v1.1.2</a> - 2018-11-11<a class="headerlink" href="#v1-1-2-2018-11-11" title="Link to this heading">¶</a></h2>
|
||
<section id="id142">
|
||
<h3>Fixed<a class="headerlink" href="#id142" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Minor fixes for Open API</p></li>
|
||
<li><p>Typos</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-1-1-2018-10-29">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.1.0..v1.1.1">v1.1.1</a> - 2018-10-29<a class="headerlink" href="#v1-1-1-2018-10-29" title="Link to this heading">¶</a></h2>
|
||
<section id="id143">
|
||
<h3>Changed<a class="headerlink" href="#id143" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Run sync views in a threadpoolexecutor.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-1-0-2018-10-27">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.0.5..v1.1.0">v1.1.0</a> - 2018-10-27<a class="headerlink" href="#v1-1-0-2018-10-27" title="Link to this heading">¶</a></h2>
|
||
<section id="id144">
|
||
<h3>Added<a class="headerlink" href="#id144" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Support for <code class="docutils literal notranslate"><span class="pre">before_request</span></code>.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-0-5-2018-10-27">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.0.4..v1.0.5">v1.0.5</a>- 2018-10-27<a class="headerlink" href="#v1-0-5-2018-10-27" title="Link to this heading">¶</a></h2>
|
||
<section id="id145">
|
||
<h3>Fixed<a class="headerlink" href="#id145" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Fix sessions.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-0-4-2018-10-27">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.0.3..v1.0.4">v1.0.4</a> - 2018-10-27<a class="headerlink" href="#v1-0-4-2018-10-27" title="Link to this heading">¶</a></h2>
|
||
<section id="id146">
|
||
<h3>Fixed<a class="headerlink" href="#id146" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Potential bufix for cookies.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-0-3-2018-10-27">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.0.2..v1.0.3">v1.0.3</a> - 2018-10-27<a class="headerlink" href="#v1-0-3-2018-10-27" title="Link to this heading">¶</a></h2>
|
||
<section id="id147">
|
||
<h3>Fixed<a class="headerlink" href="#id147" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Bugfix for redirects.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-0-2-2018-10-27">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.0.1..v1.0.2">v1.0.2</a> - 2018-10-27<a class="headerlink" href="#v1-0-2-2018-10-27" title="Link to this heading">¶</a></h2>
|
||
<section id="id148">
|
||
<h3>Changed<a class="headerlink" href="#id148" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Improvement for static file hosting.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-0-1-2018-10-26">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v1.0.0..v1.0.1">v1.0.1</a> - 2018-10-26<a class="headerlink" href="#v1-0-1-2018-10-26" title="Link to this heading">¶</a></h2>
|
||
<section id="id149">
|
||
<h3>Changed<a class="headerlink" href="#id149" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Improve cors configuration settings.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v1-0-0-2018-10-26">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.3.3..v1.0.0">v1.0.0</a> - 2018-10-26<a class="headerlink" href="#v1-0-0-2018-10-26" title="Link to this heading">¶</a></h2>
|
||
<section id="id150">
|
||
<h3>Changed<a class="headerlink" href="#id150" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Move GraphQL support into a built-in plugin.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-3-3-2018-10-25">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.3.2..v0.3.3">v0.3.3</a> - 2018-10-25<a class="headerlink" href="#v0-3-3-2018-10-25" title="Link to this heading">¶</a></h2>
|
||
<section id="id151">
|
||
<h3>Added<a class="headerlink" href="#id151" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>CORS support</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id152">
|
||
<h3>Changed<a class="headerlink" href="#id152" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Improved exceptions.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-3-2-2018-10-25">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.3.1..v0.3.2">v0.3.2</a> - 2018-10-25<a class="headerlink" href="#v0-3-2-2018-10-25" title="Link to this heading">¶</a></h2>
|
||
<section id="id153">
|
||
<h3>Changed<a class="headerlink" href="#id153" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Subtle improvements.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-3-1-2018-10-24">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.3.0..v0.3.1">v0.3.1</a> - 2018-10-24<a class="headerlink" href="#v0-3-1-2018-10-24" title="Link to this heading">¶</a></h2>
|
||
<section id="id154">
|
||
<h3>Fixed<a class="headerlink" href="#id154" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Packaging fix.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-3-0-2018-10-24">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.2.3..v0.3.0">v0.3.0</a> - 2018-10-24<a class="headerlink" href="#v0-3-0-2018-10-24" title="Link to this heading">¶</a></h2>
|
||
<section id="id155">
|
||
<h3>Changed<a class="headerlink" href="#id155" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Interactive Documentation endpoint.</p></li>
|
||
<li><p>Minor improvements.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-2-3-2018-10-24">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.2.2..v0.2.3">v0.2.3</a> - 2018-10-24<a class="headerlink" href="#v0-2-3-2018-10-24" title="Link to this heading">¶</a></h2>
|
||
<section id="id156">
|
||
<h3>Changed<a class="headerlink" href="#id156" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Overall improvements.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-2-2-2018-10-23">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.2.1..v0.2.2">v0.2.2</a> - 2018-10-23<a class="headerlink" href="#v0-2-2-2018-10-23" title="Link to this heading">¶</a></h2>
|
||
<section id="id157">
|
||
<h3>Added<a class="headerlink" href="#id157" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Show traceback info when background tasks raise exceptions.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-2-1-2018-10-23">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.2.0..v0.2.1">v0.2.1</a> - 2018-10-23<a class="headerlink" href="#v0-2-1-2018-10-23" title="Link to this heading">¶</a></h2>
|
||
<section id="id158">
|
||
<h3>Added<a class="headerlink" href="#id158" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>api.requests.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-2-0-2018-10-22">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.1.6..v0.2.0">v0.2.0</a> - 2018-10-22<a class="headerlink" href="#v0-2-0-2018-10-22" title="Link to this heading">¶</a></h2>
|
||
<section id="id159">
|
||
<h3>Added<a class="headerlink" href="#id159" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>WebSocket support.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-1-6-2018-10-20">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.1.5..v0.1.6">v0.1.6</a> - 2018-10-20<a class="headerlink" href="#v0-1-6-2018-10-20" title="Link to this heading">¶</a></h2>
|
||
<section id="id160">
|
||
<h3>Added<a class="headerlink" href="#id160" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>500 support.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-1-5-2018-10-20">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.1.4..v0.1.5">v0.1.5</a> - 2018-10-20<a class="headerlink" href="#v0-1-5-2018-10-20" title="Link to this heading">¶</a></h2>
|
||
<section id="id161">
|
||
<h3>Added<a class="headerlink" href="#id161" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>File upload support</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id162">
|
||
<h3>Changed<a class="headerlink" href="#id162" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Improvements to sequential media reading.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-1-4-2018-10-19">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.1.3..v0.1.4">v0.1.4</a> - 2018-10-19<a class="headerlink" href="#v0-1-4-2018-10-19" title="Link to this heading">¶</a></h2>
|
||
<section id="id163">
|
||
<h3>Fixed<a class="headerlink" href="#id163" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Stability.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-1-3-2018-10-18">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.1.2..v0.1.3">v0.1.3</a> - 2018-10-18<a class="headerlink" href="#v0-1-3-2018-10-18" title="Link to this heading">¶</a></h2>
|
||
<section id="id164">
|
||
<h3>Added<a class="headerlink" href="#id164" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Sessions support.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-1-2-2018-10-18">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.1.1..v0.1.2">v0.1.2</a> - 2018-10-18<a class="headerlink" href="#v0-1-2-2018-10-18" title="Link to this heading">¶</a></h2>
|
||
<section id="id165">
|
||
<h3>Added<a class="headerlink" href="#id165" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Cookies support.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-1-1-2018-10-17">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.1.0..v0.1.1">v0.1.1</a> - 2018-10-17<a class="headerlink" href="#v0-1-1-2018-10-17" title="Link to this heading">¶</a></h2>
|
||
<section id="id166">
|
||
<h3>Changed<a class="headerlink" href="#id166" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Default routes.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-1-0-2018-10-17">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.10..v0.1.0">v0.1.0</a> - 2018-10-17<a class="headerlink" href="#v0-1-0-2018-10-17" title="Link to this heading">¶</a></h2>
|
||
<section id="id167">
|
||
<h3>Added<a class="headerlink" href="#id167" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Prototype of static application support.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-10-2018-10-17">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.9..v0.0.10">v0.0.10</a> - 2018-10-17<a class="headerlink" href="#v0-0-10-2018-10-17" title="Link to this heading">¶</a></h2>
|
||
<section id="id168">
|
||
<h3>Fixed<a class="headerlink" href="#id168" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Bugfix for async class-based views.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-9-2018-10-17">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.8..v0.0.9">v0.0.9</a> - 2018-10-17<a class="headerlink" href="#v0-0-9-2018-10-17" title="Link to this heading">¶</a></h2>
|
||
<section id="id169">
|
||
<h3>Fixed<a class="headerlink" href="#id169" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Bugfix for async class-based views.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-8-2018-10-17">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.7..v0.0.8">v0.0.8</a> - 2018-10-17<a class="headerlink" href="#v0-0-8-2018-10-17" title="Link to this heading">¶</a></h2>
|
||
<section id="id170">
|
||
<h3>Added<a class="headerlink" href="#id170" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>GraphiQL Support.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id171">
|
||
<h3>Changed<a class="headerlink" href="#id171" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Improvement to route selection.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-7-2018-10-16">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.6..v0.0.7">v0.0.7</a> - 2018-10-16<a class="headerlink" href="#v0-0-7-2018-10-16" title="Link to this heading">¶</a></h2>
|
||
<section id="id172">
|
||
<h3>Changed<a class="headerlink" href="#id172" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Immutable Request object.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-6-2018-10-16">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.5..v0.0.6">v0.0.6</a> - 2018-10-16<a class="headerlink" href="#v0-0-6-2018-10-16" title="Link to this heading">¶</a></h2>
|
||
<section id="id173">
|
||
<h3>Added<a class="headerlink" href="#id173" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Ability to mount WSGI apps.</p></li>
|
||
<li><p>Supply content-type when serving up the schema.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-5-2018-10-15">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.4..v0.0.5">v0.0.5</a> - 2018-10-15<a class="headerlink" href="#v0-0-5-2018-10-15" title="Link to this heading">¶</a></h2>
|
||
<section id="id174">
|
||
<h3>Added<a class="headerlink" href="#id174" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>OpenAPI Schema support.</p></li>
|
||
<li><p>Safe load/dump yaml.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-4-2018-10-15">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.3..v0.0.4">v0.0.4</a> - 2018-10-15<a class="headerlink" href="#v0-0-4-2018-10-15" title="Link to this heading">¶</a></h2>
|
||
<section id="id175">
|
||
<h3>Added<a class="headerlink" href="#id175" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Asynchronous support for data uploads.</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="id176">
|
||
<h3>Fixed<a class="headerlink" href="#id176" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Bug fixes.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-3-2018-10-13">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.2..v0.0.3">v0.0.3</a> - 2018-10-13<a class="headerlink" href="#v0-0-3-2018-10-13" title="Link to this heading">¶</a></h2>
|
||
<section id="id177">
|
||
<h3>Fixed<a class="headerlink" href="#id177" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Bug fixes.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-2-2018-10-13">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.1..v0.0.2">v0.0.2</a> - 2018-10-13<a class="headerlink" href="#v0-0-2-2018-10-13" title="Link to this heading">¶</a></h2>
|
||
<section id="id178">
|
||
<h3>Changed<a class="headerlink" href="#id178" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Switch to ASGI/Starlette.</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="v0-0-1-2018-10-12">
|
||
<h2><a class="reference external" href="https://github.com/kennethreitz/responder/compare/v0.0.0..v0.0.1">v0.0.1</a> - 2018-10-12<a class="headerlink" href="#v0-0-1-2018-10-12" title="Link to this heading">¶</a></h2>
|
||
<section id="id179">
|
||
<h3>Added<a class="headerlink" href="#id179" title="Link to this heading">¶</a></h3>
|
||
<ul class="simple">
|
||
<li><p>Conception!</p></li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||
<div class="sphinxsidebarwrapper"><p class="logo">
|
||
<a href="index.html">
|
||
<img class="logo" src="_static/responder.png" />
|
||
</a>
|
||
</p>
|
||
<p>
|
||
<strong>Responder</strong> — a familiar HTTP service framework for Python.
|
||
<br />
|
||
<small>v9.2.0</small>
|
||
</p>
|
||
<h3>Useful Links</h3>
|
||
<ul>
|
||
<li><a href="https://github.com/kennethreitz/responder">Responder @ GitHub</a></li>
|
||
<li><a href="https://pypi.org/project/responder/">Responder @ PyPI</a></li>
|
||
<li><a href="https://github.com/kennethreitz/responder/issues">Issue Tracker</a></li>
|
||
</ul><h3>Navigation</h3>
|
||
<p class="caption" role="heading"><span class="caption-text">User Guide</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="quickstart.html">Quick Start</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tour.html">Feature Tour</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="examples.html">Examples</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="routers.html">Composing Apps with Routers</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="guide-config.html">Configuration</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="clientgen.html">Generated Clients</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="deployment.html">Deployment</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="testing.html">Testing</a></li>
|
||
</ul>
|
||
<p class="caption" role="heading"><span class="caption-text">Tutorials</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-rest.html">Building a REST API</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-sqlalchemy.html">Using SQLAlchemy</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-auth.html">Authentication</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-websockets.html">WebSocket Tutorial</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-middleware.html">Writing Middleware</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-flask.html">Migrating from Flask</a></li>
|
||
</ul>
|
||
<p class="caption" role="heading"><span class="caption-text">Reference</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="api.html">API Reference</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="cli.html">Command Line Interface</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="runtime-contracts.html">Runtime Contracts</a></li>
|
||
</ul>
|
||
<p class="caption" role="heading"><span class="caption-text">Project</span></p>
|
||
<ul class="current">
|
||
<li class="toctree-l1 current"><a class="current reference internal" href="#">Changelog</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="migration-v9.html">Migrating to v9</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="migration-v8.html">Migrating to v8</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="migration-v7.html">Migrating to v7</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="migration-v6.html">Migrating to v6</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="migration-v5.html">Migrating to v5</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="sandbox.html">Sandbox</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="backlog.html">Backlog</a></li>
|
||
</ul>
|
||
|
||
<div class="relations">
|
||
<h3>Related Topics</h3>
|
||
<ul>
|
||
<li><a href="index.html">Documentation overview</a><ul>
|
||
<li>Previous: <a href="runtime-contracts.html" title="previous chapter">Runtime Contracts</a></li>
|
||
<li>Next: <a href="migration-v9.html" title="next chapter">Migrating to v9</a></li>
|
||
</ul></li>
|
||
</ul>
|
||
</div>
|
||
<search id="searchbox" style="display: none" role="search">
|
||
<h3 id="searchlabel">Quick search</h3>
|
||
<div class="searchformwrapper">
|
||
<form class="search" action="search.html" method="get">
|
||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||
<input type="submit" value="Go" />
|
||
</form>
|
||
</div>
|
||
</search>
|
||
<script>document.getElementById('searchbox').style.display = "block"</script>
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="footer">
|
||
©2018-2026, Kenneth Reitz.
|
||
|
||
|
|
||
<a href="_sources/changes.md.txt"
|
||
rel="nofollow">Page source</a>
|
||
</div>
|
||
|
||
|
||
<a href="https://github.com/kennethreitz/responder" class="github">
|
||
<img src="_static/forkme_right_darkblue.png" alt="Fork me on GitHub" class="github"/>
|
||
</a>
|
||
|
||
|
||
|
||
</body>
|
||
</html> |