Files
responder/quickstart.html
T
2026-04-12 22:12:14 +00:00

467 lines
41 KiB
HTML
Raw 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 3.6.2 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=27fed22d" />
<link rel="stylesheet" type="text/css" href="_static/copybutton.css?v=76b2166b" />
<link rel="stylesheet" type="text/css" href="_static/design-elements.e5416f61bae5d36adc6d722a2b6f8cff.css?v=452a8e97" />
<script src="_static/documentation_options.js?v=c0c9fa11"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="_static/clipboard.min.js?v=a7894cd8"></script>
<script src="_static/copybutton.js?v=fd10adb8"></script>
<script>
</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, youll 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>Thats 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>
</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 isnt 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>Heres 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>You dont return anything. Instead, you <em>mutate</em> the response object
directly. This is a deliberate design choice — it keeps the API
consistent whether youre setting text, JSON, headers, cookies, or
status codes.</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 youll 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.</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 Pythons 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>, theyll get a 404 — the route wont
match because <code class="docutils literal notranslate"><span class="pre">hello</span></code> isnt 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 any
JSON-serializable Python object — a dict, a list, whatever — and Responder
will serialize it to JSON and set the right headers:</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/x-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 Pythons <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><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 <code class="docutils literal notranslate"><span class="pre">301</span> <span class="pre">Moved</span> <span class="pre">Permanently</span></code> response by default. The clients
browser will automatically follow the redirect.</p>
</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 its 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. (lowercase)</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><strong>Headers</strong> — HTTP headers carry metadata from the client, like what
content types it accepts, authentication tokens, and more. Responders
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,
youll need to convert it yourself: <code class="docutils literal notranslate"><span class="pre">int(req.params[&quot;page&quot;])</span></code>.</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 arent 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><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, server-side 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>
</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">api.template()</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">html</span> <span class="o">=</span> <span class="n">api</span><span class="o">.</span><span class="n">template</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>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 dont 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>Heres 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>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="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>v3.6.2</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>
<div>
<h3><a href="index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Quick Start</a><ul>
<li><a class="reference internal" href="#create-a-web-service">Create a Web Service</a></li>
<li><a class="reference internal" href="#hello-world">Hello World</a></li>
<li><a class="reference internal" href="#run-the-server">Run the Server</a></li>
<li><a class="reference internal" href="#route-parameters">Route Parameters</a><ul>
<li><a class="reference internal" href="#type-convertors">Type Convertors</a></li>
</ul>
</li>
<li><a class="reference internal" href="#sending-responses">Sending Responses</a></li>
<li><a class="reference internal" href="#reading-requests">Reading Requests</a></li>
<li><a class="reference internal" href="#rendering-templates">Rendering Templates</a></li>
<li><a class="reference internal" href="#background-tasks">Background Tasks</a></li>
<li><a class="reference internal" href="#putting-it-all-together">Putting It All Together</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>
</body>
</html>