mirror of
https://github.com/kennethreitz/responder.git
synced 2026-06-05 14:50:19 +00:00
467 lines
41 KiB
HTML
467 lines
41 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 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, 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>
|
||
</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>You don’t return anything. Instead, you <em>mutate</em> the response object
|
||
directly. This is a deliberate design choice — it keeps the API
|
||
consistent whether you’re 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 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.</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 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">"/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/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 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><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 <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 client’s
|
||
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 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. (lowercase)</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><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><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><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'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">"/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">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">"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>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>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">
|
||
©2018-2026, Kenneth Reitz.
|
||
|
||
|
|
||
<a href="_sources/quickstart.rst.txt"
|
||
rel="nofollow">Page source</a>
|
||
</div>
|
||
|
||
|
||
|
||
|
||
</body>
|
||
</html> |