mirror of
https://github.com/kennethreitz/responder.git
synced 2026-10-24 05:59:12 +00:00
613 lines
59 KiB
HTML
613 lines
59 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>Quick Start — 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="auto"</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">"import secrets; print(secrets.token_urlsafe(32))"</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">"/"</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">"hello, world!"</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">"/hello/</span><span class="si">{who}</span><span class="s2">"</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">"hello, </span><span class="si">{</span><span class="n">who</span><span class="si">}</span><span class="s2">!"</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">"/add/{a:int}/{b:int}"</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">"</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">"</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">"plain text response"</span>
|
||
<span class="n">resp</span><span class="o">.</span><span class="n">html</span> <span class="o">=</span> <span class="s2">"<h1>HTML response</h1>"</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">"/hello/</span><span class="si">{who}</span><span class="s2">/json"</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">"hello"</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">"reports/annual.pdf"</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="reports")</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">"</span><span class="se">\x89</span><span class="s2">PNG</span><span class="se">\r\n</span><span class="s2">..."</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">"X-Custom"</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"value"</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">"/new-url"</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">"/"</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">"hello, world!"</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">"created"</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">"Location"</span><span class="p">:</span> <span class="s2">"/items/1"</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">"/items"</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">-></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">"/items/</span><span class="si">{item_id}</span><span class="s2">"</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">-></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">"Item not found"</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"># "GET", "POST", etc. (uppercase)</span>
|
||
<span class="n">req</span><span class="o">.</span><span class="n">full_url</span> <span class="c1"># "http://example.com/path?q=1"</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">"POST"</span></code>);
|
||
membership tests like <code class="docutils literal notranslate"><span class="pre">req.method</span> <span class="pre">in</span> <span class="pre">{"get"}</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">"Content-Type"</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">"content-type"</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&page=2</span>
|
||
<span class="n">req</span><span class="o">.</span><span class="n">params</span><span class="p">[</span><span class="s2">"q"</span><span class="p">]</span> <span class="c1"># "python"</span>
|
||
<span class="n">req</span><span class="o">.</span><span class="n">params</span><span class="p">[</span><span class="s2">"page"</span><span class="p">]</span> <span class="c1"># "2"</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["page"])</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">"/search"</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">"q"</span><span class="p">:</span> <span class="n">q</span><span class="p">,</span> <span class="s2">"page"</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">"user_id"</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">"form"</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">"files"</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">"/items"</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">"POST"</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">"created"</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'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">"/hello/</span><span class="si">{name}</span><span class="s2">/html"</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">"hello.html"</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("hello.html",</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><h1>Hello, {{ name }}!</h1>
|
||
</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">"my_templates"</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">"/page"</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">"page.html"</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="s2">"Hello"</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">"templates"</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">"page.html"</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="s2">"Hello"</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">"Hello, {{ name }}!"</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s2">"world"</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">@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">"/incoming"</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">"""This runs in a background thread."""</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">"status"</span><span class="p">:</span> <span class="s2">"accepted"</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">"/"</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">"Welcome to the API"</span>
|
||
|
||
<span class="nd">@api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">"/hello/</span><span class="si">{name}</span><span class="s2">"</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">"message"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"hello, </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">!"</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">"/add/{a:int}/{b:int}"</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">"result"</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">"/echo"</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">"POST"</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">"received"</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">"__main__"</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 "Content-Type: application/json" -d '{"key": "value"}'
|
||
</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">
|
||
©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> |