Files
responder/quickstart.html
2026-07-14 04:14:56 +00:00

613 lines
59 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>Quick Start &#8212; 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="Feature Tour" href="tour.html" />
<link rel="prev" title="Responder" href="index.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="quick-start">
<h1>Quick Start<a class="headerlink" href="#quick-start" title="Link to this heading"></a></h1>
<p>This guide will walk you through the basics of building a web service with
Responder. By the end, you’ll understand how HTTP requests and responses
work, how to define routes, read data from clients, send data back, render
HTML templates, and process work in the background.</p>
<section id="create-a-web-service">
<h2>Create a Web Service<a class="headerlink" href="#create-a-web-service" title="Link to this heading"></a></h2>
<p>Every web application starts with a single object — the application
instance. In Responder, this is the <code class="docutils literal notranslate"><span class="pre">API</span></code> class. It holds your routes,
middleware, templates, and configuration. Think of it as the central
nervous system of your web service:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">responder</span>
<span class="n">api</span> <span class="o">=</span> <span class="n">responder</span><span class="o">.</span><span class="n">API</span><span class="p">()</span>
</pre></div>
</div>
<p>That’s it. One import, one line. You now have a fully functional ASGI
application with gzip compression, static file serving, session support,
and a production-ready server — all wired up and ready to go.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>With the default <code class="docutils literal notranslate"><span class="pre">sessions=&quot;auto&quot;</span></code>, an app with no signing key mints a
random one per process and logs a startup warning. That’s fine for a
first run, but set a real <code class="docutils literal notranslate"><span class="pre">secret_key</span></code> (or the <code class="docutils literal notranslate"><span class="pre">RESPONDER_SECRET_KEY</span></code>
environment variable) for stable, multi-worker sessions — otherwise a new
key each restart logs everyone out. Generate one with:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">c</span> <span class="s2">&quot;import secrets; print(secrets.token_urlsafe(32))&quot;</span>
</pre></div>
</div>
<p>See <a class="reference internal" href="guide-config.html"><span class="doc">Configuration</span></a> for the full configuration story.</p>
</div>
</section>
<section id="hello-world">
<h2>Hello World<a class="headerlink" href="#hello-world" title="Link to this heading"></a></h2>
<p>A web service isn’t very useful until it can respond to requests. In HTTP,
a <em>route</em> maps a URL path to a function that handles it. When a client
(like a browser or <code class="docutils literal notranslate"><span class="pre">curl</span></code>) sends a request to that path, your function
runs and produces a response.</p>
<p>Here’s the simplest possible route:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">hello_world</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s2">&quot;hello, world!&quot;</span>
</pre></div>
</div>
<p>Two things to notice:</p>
<ol class="arabic simple">
<li><p>Every view function receives two arguments: <code class="docutils literal notranslate"><span class="pre">req</span></code> (the incoming
request) and <code class="docutils literal notranslate"><span class="pre">resp</span></code> (the outgoing response).</p></li>
<li><p>The handler <em>mutates</em> the response object directly rather than
returning it. This keeps the API consistent whether you’re setting
text, JSON, headers, cookies, or status codes. (If you prefer the
Flask style, a handler may also <a class="reference internal" href="#returning-values"><span class="std std-ref">return a value</span></a>.)</p></li>
</ol>
</section>
<section id="run-the-server">
<h2>Run the Server<a class="headerlink" href="#run-the-server" title="Link to this heading"></a></h2>
<p>Start your web service with a single call:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">api</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>This spins up a production-grade <a class="reference external" href="https://www.uvicorn.org/">uvicorn</a>
server on port <code class="docutils literal notranslate"><span class="pre">5042</span></code>, ready for incoming HTTP requests. Open
<code class="docutils literal notranslate"><span class="pre">http://localhost:5042</span></code> in your browser and you’ll see your hello world
response.</p>
<p>You can customize the port with <code class="docutils literal notranslate"><span class="pre">api.run(port=8000)</span></code>. The <code class="docutils literal notranslate"><span class="pre">PORT</span></code>
environment variable is also honored automatically — when set, Responder
binds to <code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> on that port, which is what cloud platforms expect.
When both are set, the explicit <code class="docutils literal notranslate"><span class="pre">port=</span></code> wins.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Both sync and async views are supported. The <code class="docutils literal notranslate"><span class="pre">async</span></code> keyword is always
optional — use it when you need to <code class="docutils literal notranslate"><span class="pre">await</span></code> something, like reading a
request body or querying a database.</p>
</div>
</section>
<section id="route-parameters">
<h2>Route Parameters<a class="headerlink" href="#route-parameters" title="Link to this heading"></a></h2>
<p>Static URLs like <code class="docutils literal notranslate"><span class="pre">/about</span></code> are useful, but most applications need dynamic
routes — URLs that contain variable data, like a user ID or a product slug.</p>
<p>In Responder, you declare route parameters using Python’s f-string syntax:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/hello/</span><span class="si">{who}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">hello_to</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">who</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;hello, </span><span class="si">{</span><span class="n">who</span><span class="si">}</span><span class="s2">!&quot;</span>
</pre></div>
</div>
<p>A <code class="docutils literal notranslate"><span class="pre">GET</span></code> request to <code class="docutils literal notranslate"><span class="pre">/hello/world</span></code> will respond with <code class="docutils literal notranslate"><span class="pre">hello,</span> <span class="pre">world!</span></code>.
A request to <code class="docutils literal notranslate"><span class="pre">/hello/guido</span></code> will respond with <code class="docutils literal notranslate"><span class="pre">hello,</span> <span class="pre">guido!</span></code>.</p>
<p>Route parameters are passed as <em>keyword-only</em> arguments (after the <code class="docutils literal notranslate"><span class="pre">*</span></code>
in the function signature). This is a Python feature that makes the
interface explicit — you always know which arguments come from the URL.</p>
<section id="type-convertors">
<h3>Type Convertors<a class="headerlink" href="#type-convertors" title="Link to this heading"></a></h3>
<p>By default, route parameters are strings. But often you want them as
integers, UUIDs, or other types. Responder can convert them automatically
using type annotations in the route pattern:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/add/{a:int}/{b:int}&quot;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">add</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">a</span><span class="si">}</span><span class="s2"> + </span><span class="si">{</span><span class="n">b</span><span class="si">}</span><span class="s2"> = </span><span class="si">{</span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">b</span><span class="si">}</span><span class="s2">&quot;</span>
</pre></div>
</div>
<p>Here, <code class="docutils literal notranslate"><span class="pre">a</span></code> and <code class="docutils literal notranslate"><span class="pre">b</span></code> will arrive as Python <code class="docutils literal notranslate"><span class="pre">int</span></code> objects, not strings.
If someone requests <code class="docutils literal notranslate"><span class="pre">/add/3/hello</span></code>, they’ll get a 404 — the route won’t
match because <code class="docutils literal notranslate"><span class="pre">hello</span></code> isn’t a valid integer.</p>
<p>Supported types:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">str</span></code> — matches any string without slashes (this is the default)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">int</span></code> — matches digits and converts to <code class="docutils literal notranslate"><span class="pre">int</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">float</span></code> — matches decimal numbers and converts to <code class="docutils literal notranslate"><span class="pre">float</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">uuid</span></code> — matches UUID strings like <code class="docutils literal notranslate"><span class="pre">550e8400-e29b-41d4-a716-446655440000</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">path</span></code> — matches any string <em>including</em> slashes, useful for file paths
like <code class="docutils literal notranslate"><span class="pre">/files/{filepath:path}</span></code></p></li>
</ul>
</section>
</section>
<section id="sending-responses">
<h2>Sending Responses<a class="headerlink" href="#sending-responses" title="Link to this heading"></a></h2>
<p>When an HTTP server receives a request, it must send back a response. Every
HTTP response has three parts: a status code (like <code class="docutils literal notranslate"><span class="pre">200</span> <span class="pre">OK</span></code> or <code class="docutils literal notranslate"><span class="pre">404</span> <span class="pre">Not</span>
<span class="pre">Found</span></code>), headers (metadata like <code class="docutils literal notranslate"><span class="pre">Content-Type</span></code>), and a body (the actual
data).</p>
<p>Responder lets you set all three by mutating the response object.</p>
<p><strong>Text and HTML</strong> — the simplest response types. <code class="docutils literal notranslate"><span class="pre">resp.text</span></code> sets the
<code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> to <code class="docutils literal notranslate"><span class="pre">text/plain</span></code>, while <code class="docutils literal notranslate"><span class="pre">resp.html</span></code> sets it to
<code class="docutils literal notranslate"><span class="pre">text/html</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">resp</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s2">&quot;plain text response&quot;</span>
<span class="n">resp</span><span class="o">.</span><span class="n">html</span> <span class="o">=</span> <span class="s2">&quot;&lt;h1&gt;HTML response&lt;/h1&gt;&quot;</span>
</pre></div>
</div>
<p><strong>JSON</strong> — the lingua franca of web APIs. Set <code class="docutils literal notranslate"><span class="pre">resp.media</span></code> to a dict, a
list, or any JSON-serializable object and Responder serializes it and sets
the right headers. Pydantic models and dataclasses work too, as do rich
types like <code class="docutils literal notranslate"><span class="pre">datetime</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>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/hello/</span><span class="si">{who}</span><span class="s2">/json&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">hello_json</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">who</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">media</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;hello&quot;</span><span class="p">:</span> <span class="n">who</span><span class="p">}</span>
</pre></div>
</div>
<p>If the client sends an <code class="docutils literal notranslate"><span class="pre">Accept:</span> <span class="pre">application/yaml</span></code> header, the same data
will be returned as YAML instead. This is called <em>content negotiation</em> —
the server and client agree on a format. It happens automatically.</p>
<p><strong>Files</strong> — serve a file from disk. Responder uses Python’s <code class="docutils literal notranslate"><span class="pre">mimetypes</span></code>
module to figure out the <code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> from the file extension:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">resp</span><span class="o">.</span><span class="n">file</span><span class="p">(</span><span class="s2">&quot;reports/annual.pdf&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>When the path comes from user input, pass <code class="docutils literal notranslate"><span class="pre">root=</span></code> to jail it to a
directory: <code class="docutils literal notranslate"><span class="pre">resp.file(path,</span> <span class="pre">root=&quot;reports&quot;)</span></code> resolves under <code class="docutils literal notranslate"><span class="pre">reports/</span></code>
and returns a <code class="docutils literal notranslate"><span class="pre">404</span></code> for any <code class="docutils literal notranslate"><span class="pre">../</span></code> or symlink escape. The same guard
applies to <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>.</p>
<p><strong>Raw bytes</strong> — for binary data like images or protocol buffers:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">resp</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="sa">b</span><span class="s2">&quot;</span><span class="se">\x89</span><span class="s2">PNG</span><span class="se">\r\n</span><span class="s2">...&quot;</span>
</pre></div>
</div>
<p><strong>Status codes</strong> — HTTP status codes tell the client what happened. <code class="docutils literal notranslate"><span class="pre">200</span></code>
means success, <code class="docutils literal notranslate"><span class="pre">201</span></code> means something was created, <code class="docutils literal notranslate"><span class="pre">404</span></code> means not found,
<code class="docutils literal notranslate"><span class="pre">500</span></code> means the server broke. Set it directly:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">resp</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="mi">201</span>
</pre></div>
</div>
<p><strong>Headers</strong> — HTTP headers carry metadata. Common ones include
<code class="docutils literal notranslate"><span class="pre">Content-Type</span></code>, <code class="docutils literal notranslate"><span class="pre">Cache-Control</span></code>, <code class="docutils literal notranslate"><span class="pre">Authorization</span></code>, and custom
application headers:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">resp</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s2">&quot;X-Custom&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;value&quot;</span>
</pre></div>
</div>
<p><strong>Redirects</strong> — tell the client to go somewhere else:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">api</span><span class="o">.</span><span class="n">redirect</span><span class="p">(</span><span class="n">resp</span><span class="p">,</span> <span class="n">location</span><span class="o">=</span><span class="s2">&quot;/new-url&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>This sends a method-preserving <code class="docutils literal notranslate"><span class="pre">307</span> <span class="pre">Temporary</span> <span class="pre">Redirect</span></code> by default; 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>, or an explicit
<code class="docutils literal notranslate"><span class="pre">status_code=</span></code>. For a user-supplied target (like a <code class="docutils literal notranslate"><span class="pre">?next=</span></code> parameter),
pass <code class="docutils literal notranslate"><span class="pre">allow_external=False</span></code> to refuse absolute or protocol-relative URLs
and prevent open redirects.</p>
<p id="returning-values"><strong>Returning values</strong> — mutating <code class="docutils literal notranslate"><span class="pre">resp</span></code> is the primary style, but a
handler may also <code class="docutils literal notranslate"><span class="pre">return</span></code> a value, Flask-style. A string becomes the
body, bytes become a binary body, and dictionaries, lists, numeric/boolean
scalars, Pydantic models, and dataclasses are serialized for you:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">):</span>
<span class="k">return</span> <span class="s2">&quot;hello, world!&quot;</span>
</pre></div>
</div>
<p>Return a <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> tuple to set the
status code and headers in one go:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">return</span> <span class="p">{</span><span class="s2">&quot;created&quot;</span><span class="p">:</span> <span class="kc">True</span><span class="p">},</span> <span class="mi">201</span><span class="p">,</span> <span class="p">{</span><span class="s2">&quot;Location&quot;</span><span class="p">:</span> <span class="s2">&quot;/items/1&quot;</span><span class="p">}</span>
</pre></div>
</div>
<p>A supported return annotation is a complete response contract. It validates
and serializes the outgoing value, generates the OpenAPI response schema, and
types generated clients:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@api</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/items&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">list_items</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="n">ItemOut</span><span class="p">]:</span>
<span class="k">return</span> <span class="n">items</span>
</pre></div>
</div>
<p>Models, dataclasses, typed dictionaries, collections, unions, pagination
models, and JSON scalars are supported. Invalid success responses fail closed
with <code class="docutils literal notranslate"><span class="pre">500</span></code>; pass <code class="docutils literal notranslate"><span class="pre">response_model=False</span></code> on the route to opt out. String and
bytes annotations describe <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>
<p>Give alternate statuses their own contract with <code class="docutils literal notranslate"><span class="pre">responses=</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@api</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/items/</span><span class="si">{item_id}</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">responses</span><span class="o">=</span><span class="p">{</span><span class="mi">404</span><span class="p">:</span> <span class="n">NotFound</span><span class="p">})</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_item</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">item_id</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">ItemOut</span><span class="p">:</span>
<span class="n">item</span> <span class="o">=</span> <span class="n">find_item</span><span class="p">(</span><span class="n">item_id</span><span class="p">)</span>
<span class="k">if</span> <span class="n">item</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">return</span> <span class="n">NotFound</span><span class="p">(</span><span class="n">detail</span><span class="o">=</span><span class="s2">&quot;Item not found&quot;</span><span class="p">),</span> <span class="mi">404</span>
<span class="k">return</span> <span class="n">item</span>
</pre></div>
</div>
</section>
<section id="reading-requests">
<h2>Reading Requests<a class="headerlink" href="#reading-requests" title="Link to this heading"></a></h2>
<p>The other half of HTTP is the request — the data the client sends to your
server. This includes the HTTP method (GET, POST, PUT, DELETE), the URL,
headers, query parameters, cookies, and optionally a body.</p>
<p>Responder wraps all of this in the <code class="docutils literal notranslate"><span class="pre">req</span></code> object.</p>
<p><strong>Method and URL</strong> — every HTTP request has a method (what the client wants
to do) and a URL (what resource it’s about):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">req</span><span class="o">.</span><span class="n">method</span> <span class="c1"># &quot;GET&quot;, &quot;POST&quot;, etc. (uppercase)</span>
<span class="n">req</span><span class="o">.</span><span class="n">full_url</span> <span class="c1"># &quot;http://example.com/path?q=1&quot;</span>
<span class="n">req</span><span class="o">.</span><span class="n">url</span> <span class="c1"># parsed URL object</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">req.method</span></code> is uppercase, matching Flask, FastAPI, and the standard
library. Compare it against uppercase literals (<code class="docutils literal notranslate"><span class="pre">req.method</span> <span class="pre">==</span> <span class="pre">&quot;POST&quot;</span></code>);
membership tests like <code class="docutils literal notranslate"><span class="pre">req.method</span> <span class="pre">in</span> <span class="pre">{&quot;get&quot;}</span></code> won’t match.</p>
<p><strong>Headers</strong> — HTTP headers carry metadata from the client, like what
content types it accepts, authentication tokens, and more. Responder’s
headers dict is case-insensitive, because the HTTP spec says header names
are case-insensitive:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">req</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s2">&quot;Content-Type&quot;</span><span class="p">]</span>
<span class="n">req</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s2">&quot;content-type&quot;</span><span class="p">]</span> <span class="c1"># same thing</span>
</pre></div>
</div>
<p><strong>Query parameters</strong> — the part of the URL after the <code class="docutils literal notranslate"><span class="pre">?</span></code>. These are
commonly used for search, filtering, and pagination:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># GET /search?q=python&amp;page=2</span>
<span class="n">req</span><span class="o">.</span><span class="n">params</span><span class="p">[</span><span class="s2">&quot;q&quot;</span><span class="p">]</span> <span class="c1"># &quot;python&quot;</span>
<span class="n">req</span><span class="o">.</span><span class="n">params</span><span class="p">[</span><span class="s2">&quot;page&quot;</span><span class="p">]</span> <span class="c1"># &quot;2&quot;</span>
</pre></div>
</div>
<p>Note that query parameters are always strings. If you need an integer,
you’ll need to convert it yourself: <code class="docutils literal notranslate"><span class="pre">int(req.params[&quot;page&quot;])</span></code>.</p>
<p>For a cleaner approach, <em>typed parameters</em> let Responder read, validate,
and coerce query values for you. Import the markers and use them as the
defaults of keyword-only arguments:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">responder</span><span class="w"> </span><span class="kn">import</span> <span class="n">Query</span>
<span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/search&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">q</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="n">Query</span><span class="p">(</span><span class="o">...</span><span class="p">),</span> <span class="n">page</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="n">Query</span><span class="p">(</span><span class="mi">1</span><span class="p">)):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">media</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;q&quot;</span><span class="p">:</span> <span class="n">q</span><span class="p">,</span> <span class="s2">&quot;page&quot;</span><span class="p">:</span> <span class="n">page</span><span class="p">}</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">Query(...)</span></code> marks a required parameter; <code class="docutils literal notranslate"><span class="pre">Query(1)</span></code> supplies a default.
Values are coerced to the annotated type (<code class="docutils literal notranslate"><span class="pre">page</span></code> arrives as an <code class="docutils literal notranslate"><span class="pre">int</span></code>),
and a missing-required or un-coercible value returns a <code class="docutils literal notranslate"><span class="pre">422</span></code> automatically
— no manual casting. <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 work the
same way for those locations. See <a class="reference internal" href="tutorial-rest.html"><span class="doc">Building a REST API</span></a> for the full
typed-I/O story.</p>
<p><strong>Path parameters</strong> — the dynamic parts of the URL that matched your route
pattern. These are also available on the request object, which is useful
in before-request hooks where they aren’t passed as function arguments:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">req</span><span class="o">.</span><span class="n">path_params</span><span class="p">[</span><span class="s2">&quot;user_id&quot;</span><span class="p">]</span> <span class="c1"># same as the keyword argument</span>
</pre></div>
</div>
<p><strong>Request body</strong> — for POST, PUT, and PATCH requests, the client sends
data in the body. Since reading the body is an I/O operation, you need to
<code class="docutils literal notranslate"><span class="pre">await</span></code> it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># JSON body (the most common format for APIs)</span>
<span class="n">data</span> <span class="o">=</span> <span class="k">await</span> <span class="n">req</span><span class="o">.</span><span class="n">media</span><span class="p">()</span>
<span class="c1"># Form data (from HTML forms)</span>
<span class="n">data</span> <span class="o">=</span> <span class="k">await</span> <span class="n">req</span><span class="o">.</span><span class="n">media</span><span class="p">(</span><span class="s2">&quot;form&quot;</span><span class="p">)</span>
<span class="c1"># File uploads (multipart)</span>
<span class="n">files</span> <span class="o">=</span> <span class="k">await</span> <span class="n">req</span><span class="o">.</span><span class="n">media</span><span class="p">(</span><span class="s2">&quot;files&quot;</span><span class="p">)</span>
<span class="c1"># Raw bytes</span>
<span class="n">body</span> <span class="o">=</span> <span class="k">await</span> <span class="n">req</span><span class="o">.</span><span class="n">content</span>
<span class="c1"># Raw text</span>
<span class="n">text</span> <span class="o">=</span> <span class="k">await</span> <span class="n">req</span><span class="o">.</span><span class="n">text</span>
</pre></div>
</div>
<p>In a synchronous handler, use the blocking equivalents <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> instead of awaiting.</p>
<p>Even simpler: annotate a keyword-only parameter with a Pydantic model and
Responder parses, validates, and injects the request body for you,
returning a <code class="docutils literal notranslate"><span class="pre">422</span></code> if it doesn’t match:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">pydantic</span><span class="w"> </span><span class="kn">import</span> <span class="n">BaseModel</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Item</span><span class="p">(</span><span class="n">BaseModel</span><span class="p">):</span>
<span class="n">name</span><span class="p">:</span> <span class="nb">str</span>
<span class="n">price</span><span class="p">:</span> <span class="nb">float</span>
<span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/items&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;POST&quot;</span><span class="p">])</span>
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">create</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">item</span><span class="p">:</span> <span class="n">Item</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">media</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;created&quot;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">name</span><span class="p">}</span>
</pre></div>
</div>
<p>This is the recommended way to handle request bodies — see
<a class="reference internal" href="tutorial-rest.html"><span class="doc">Building a REST API</span></a> for the complete pattern.</p>
<p><strong>Other useful properties</strong>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">req</span><span class="o">.</span><span class="n">is_json</span> <span class="c1"># True if the content type is JSON</span>
<span class="n">req</span><span class="o">.</span><span class="n">cookies</span> <span class="c1"># dict of cookies sent by the client</span>
<span class="n">req</span><span class="o">.</span><span class="n">session</span> <span class="c1"># session data (a signed cookie-backed dict)</span>
<span class="n">req</span><span class="o">.</span><span class="n">client</span> <span class="c1"># (host, port) tuple — the client&#39;s IP address</span>
<span class="n">req</span><span class="o">.</span><span class="n">is_secure</span> <span class="c1"># True if the request came over HTTPS</span>
</pre></div>
</div>
<p>By default the session is a signed cookie. Opt into server-side storage
(memory or Redis) with a backend — see <a class="reference internal" href="guide-config.html"><span class="doc">Configuration</span></a>.</p>
</section>
<section id="rendering-templates">
<h2>Rendering Templates<a class="headerlink" href="#rendering-templates" title="Link to this heading"></a></h2>
<p>While APIs typically return JSON, many web applications need to render
HTML pages. Responder includes built-in support for
<a class="reference external" href="https://jinja.palletsprojects.com/">Jinja2</a>, one of the most popular
templating engines in the Python ecosystem.</p>
<p>Templates let you write HTML with placeholders that get filled in with
dynamic data. This keeps your presentation logic (HTML) separate from
your application logic (Python) — a pattern called
<em>separation of concerns</em>.</p>
<p>The simplest way to render a template is <code class="docutils literal notranslate"><span class="pre">resp.render()</span></code>. Templates
are loaded from the <code class="docutils literal notranslate"><span class="pre">templates/</span></code> directory by default:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/hello/</span><span class="si">{name}</span><span class="s2">/html&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">hello_html</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s2">&quot;hello.html&quot;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
</pre></div>
</div>
<p>(<code class="docutils literal notranslate"><span class="pre">resp.html</span> <span class="pre">=</span> <span class="pre">api.template(&quot;hello.html&quot;,</span> <span class="pre">name=name)</span></code> is the equivalent
long form.)</p>
<p>The template file <code class="docutils literal notranslate"><span class="pre">templates/hello.html</span></code> might look like:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>&lt;h1&gt;Hello, {{ name }}!&lt;/h1&gt;
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">{{</span> <span class="pre">name</span> <span class="pre">}}</span></code> part is a Jinja2 expression — it gets replaced with
the value you passed in.</p>
<p>You can also use the <code class="docutils literal notranslate"><span class="pre">Templates</span></code> class directly for more control over
the template directory and configuration:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">responder.templates</span><span class="w"> </span><span class="kn">import</span> <span class="n">Templates</span>
<span class="n">templates</span> <span class="o">=</span> <span class="n">Templates</span><span class="p">(</span><span class="n">directory</span><span class="o">=</span><span class="s2">&quot;my_templates&quot;</span><span class="p">)</span>
<span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/page&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">page</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">html</span> <span class="o">=</span> <span class="n">templates</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="s2">&quot;page.html&quot;</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="s2">&quot;Hello&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>For applications that need non-blocking template rendering (rare, but
useful under extreme load), async rendering is supported:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">templates</span> <span class="o">=</span> <span class="n">Templates</span><span class="p">(</span><span class="n">directory</span><span class="o">=</span><span class="s2">&quot;templates&quot;</span><span class="p">,</span> <span class="n">enable_async</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">resp</span><span class="o">.</span><span class="n">html</span> <span class="o">=</span> <span class="k">await</span> <span class="n">templates</span><span class="o">.</span><span class="n">render_async</span><span class="p">(</span><span class="s2">&quot;page.html&quot;</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="s2">&quot;Hello&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>And for quick one-off templates, you can render a string directly without
a file:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">resp</span><span class="o">.</span><span class="n">html</span> <span class="o">=</span> <span class="n">api</span><span class="o">.</span><span class="n">template_string</span><span class="p">(</span><span class="s2">&quot;Hello, {{ name }}!&quot;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s2">&quot;world&quot;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="background-tasks">
<h2>Background Tasks<a class="headerlink" href="#background-tasks" title="Link to this heading"></a></h2>
<p>Sometimes you want to accept a request, respond immediately, and do the
actual processing later. This is a common pattern for operations that take
a long time — sending emails, processing images, updating caches, or
calling slow external APIs.</p>
<p>Responder makes this easy with background tasks. Decorate any function
with <code class="docutils literal notranslate"><span class="pre">&#64;api.background.task</span></code> and it will run in a thread pool, separate
from the request/response cycle:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/incoming&quot;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">receive_incoming</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">):</span>
<span class="n">data</span> <span class="o">=</span> <span class="k">await</span> <span class="n">req</span><span class="o">.</span><span class="n">media</span><span class="p">()</span>
<span class="nd">@api</span><span class="o">.</span><span class="n">background</span><span class="o">.</span><span class="n">task</span>
<span class="k">def</span><span class="w"> </span><span class="nf">process_data</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;This runs in a background thread.&quot;&quot;&quot;</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="c1"># simulate heavy work</span>
<span class="n">process_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="c1"># This response is sent immediately, while process_data</span>
<span class="c1"># continues running in the background.</span>
<span class="n">resp</span><span class="o">.</span><span class="n">media</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;status&quot;</span><span class="p">:</span> <span class="s2">&quot;accepted&quot;</span><span class="p">}</span>
</pre></div>
</div>
<p>The client gets an instant response — the heavy lifting happens after.
This is the same pattern used by task queues like Celery, but much simpler
for lightweight use cases where you don’t need a full message broker.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Background tasks run in threads, not processes. They share memory with
your application, which makes them fast to start but means CPU-intensive
work will block the event loop. For heavy computation, consider a proper
task queue.</p>
</div>
</section>
<section id="putting-it-all-together">
<h2>Putting It All Together<a class="headerlink" href="#putting-it-all-together" title="Link to this heading"></a></h2>
<p>Here’s a complete, working Responder application that combines everything
from this guide:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">responder</span>
<span class="n">api</span> <span class="o">=</span> <span class="n">responder</span><span class="o">.</span><span class="n">API</span><span class="p">()</span>
<span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="s2">&quot;Welcome to the API&quot;</span>
<span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/hello/</span><span class="si">{name}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">greet</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">media</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;message&quot;</span><span class="p">:</span> <span class="sa">f</span><span class="s2">&quot;hello, </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">!&quot;</span><span class="p">}</span>
<span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/add/{a:int}/{b:int}&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">add</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
<span class="n">resp</span><span class="o">.</span><span class="n">media</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;result&quot;</span><span class="p">:</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">}</span>
<span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/echo&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;POST&quot;</span><span class="p">])</span>
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">echo</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">resp</span><span class="p">):</span>
<span class="n">data</span> <span class="o">=</span> <span class="k">await</span> <span class="n">req</span><span class="o">.</span><span class="n">media</span><span class="p">()</span>
<span class="n">resp</span><span class="o">.</span><span class="n">media</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;received&quot;</span><span class="p">:</span> <span class="n">data</span><span class="p">}</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
<span class="n">api</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>Save this as <code class="docutils literal notranslate"><span class="pre">app.py</span></code>, run it with <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">app.py</span></code>, and try:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ curl http://localhost:5042/
$ curl http://localhost:5042/hello/world
$ curl http://localhost:5042/add/3/4
$ curl -X POST http://localhost:5042/echo \
-H &quot;Content-Type: application/json&quot; -d &#39;{&quot;key&quot;: &quot;value&quot;}&#39;
</pre></div>
</div>
<p>You can also run the same file with the CLI:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ responder run app.py
</pre></div>
</div>
<p>From here, explore the <a class="reference internal" href="tour.html"><span class="doc">Feature Tour</span></a> for the full range of features, or
jump into the tutorials:</p>
<ul class="simple">
<li><p><a class="reference internal" href="tutorial-rest.html"><span class="doc">Building a REST API</span></a> — build a full CRUD API with validation</p></li>
<li><p><a class="reference internal" href="examples.html"><span class="doc">Examples</span></a> — run complete apps from the <code class="docutils literal notranslate"><span class="pre">examples/</span></code> directory</p></li>
<li><p><a class="reference internal" href="tutorial-sqlalchemy.html"><span class="doc">Using SQLAlchemy</span></a> — connect to a database</p></li>
<li><p><a class="reference internal" href="tutorial-auth.html"><span class="doc">Authentication</span></a> — add authentication</p></li>
<li><p><a class="reference internal" href="tutorial-websockets.html"><span class="doc">WebSocket Tutorial</span></a> — real-time communication</p></li>
<li><p><a class="reference internal" href="tutorial-middleware.html"><span class="doc">Writing Middleware</span></a> — hooks and middleware</p></li>
<li><p><a class="reference internal" href="tutorial-flask.html"><span class="doc">Migrating from Flask</span></a> — migrating from Flask</p></li>
<li><p><a class="reference internal" href="guide-config.html"><span class="doc">Configuration</span></a> — environment variables and secrets</p></li>
<li><p><a class="reference internal" href="deployment.html"><span class="doc">Deployment</span></a> — Docker, cloud platforms, and production</p></li>
<li><p><a class="reference internal" href="testing.html"><span class="doc">Testing</span></a> — writing tests with pytest</p></li>
</ul>
</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 class="current">
<li class="toctree-l1 current"><a class="current reference internal" href="#">Quick Start</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#create-a-web-service">Create a Web Service</a></li>
<li class="toctree-l2"><a class="reference internal" href="#hello-world">Hello World</a></li>
<li class="toctree-l2"><a class="reference internal" href="#run-the-server">Run the Server</a></li>
<li class="toctree-l2"><a class="reference internal" href="#route-parameters">Route Parameters</a></li>
<li class="toctree-l2"><a class="reference internal" href="#sending-responses">Sending Responses</a></li>
<li class="toctree-l2"><a class="reference internal" href="#reading-requests">Reading Requests</a></li>
<li class="toctree-l2"><a class="reference internal" href="#rendering-templates">Rendering Templates</a></li>
<li class="toctree-l2"><a class="reference internal" href="#background-tasks">Background Tasks</a></li>
<li class="toctree-l2"><a class="reference internal" href="#putting-it-all-together">Putting It All Together</a></li>
</ul>
</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>
<li class="toctree-l1"><a class="reference internal" href="changes.html">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="index.html" title="previous chapter">Responder</a></li>
<li>Next: <a href="tour.html" title="next chapter">Feature Tour</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">
&#169;2018-2026, Kenneth Reitz.
|
<a href="_sources/quickstart.rst.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>