1689 lines
138 KiB
HTML
1689 lines
138 KiB
HTML
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="color-scheme" content="light dark">
|
||
<title>PEP 333 – Python Web Server Gateway Interface v1.0 | peps.python.org</title>
|
||
<link rel="shortcut icon" href="../_static/py.png">
|
||
<link rel="canonical" href="https://peps.python.org/pep-0333/">
|
||
<link rel="stylesheet" href="../_static/style.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
|
||
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
|
||
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
|
||
<meta property="og:title" content='PEP 333 – Python Web Server Gateway Interface v1.0 | peps.python.org'>
|
||
<meta property="og:description" content="This document specifies a proposed standard interface between web servers and Python web applications or frameworks, to promote web application portability across a variety of web servers.">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://peps.python.org/pep-0333/">
|
||
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
||
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
||
<meta property="og:image:alt" content="Python PEPs">
|
||
<meta property="og:image:width" content="200">
|
||
<meta property="og:image:height" content="200">
|
||
<meta name="description" content="This document specifies a proposed standard interface between web servers and Python web applications or frameworks, to promote web application portability across a variety of web servers.">
|
||
<meta name="theme-color" content="#3776ab">
|
||
</head>
|
||
<body>
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Following system colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="9"></circle>
|
||
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected dark colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
||
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
||
</svg>
|
||
</symbol>
|
||
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
||
<title>Selected light colour scheme</title>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
</symbol>
|
||
</svg>
|
||
<script>
|
||
|
||
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
||
</script>
|
||
<section id="pep-page-section">
|
||
<header>
|
||
<h1>Python Enhancement Proposals</h1>
|
||
<ul class="breadcrumbs">
|
||
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
||
<li>PEP 333</li>
|
||
</ul>
|
||
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
||
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
||
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
||
</button>
|
||
</header>
|
||
<article>
|
||
<section id="pep-content">
|
||
<h1 class="page-title">PEP 333 – Python Web Server Gateway Interface v1.0</h1>
|
||
<dl class="rfc2822 field-list simple">
|
||
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
||
<dd class="field-odd">Phillip J. Eby <pje at telecommunity.com></dd>
|
||
<dt class="field-even">Discussions-To<span class="colon">:</span></dt>
|
||
<dd class="field-even"><a class="reference external" href="https://mail.python.org/mailman/listinfo/web-sig">Web-SIG list</a></dd>
|
||
<dt class="field-odd">Status<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
|
||
<dt class="field-even">Type<span class="colon">:</span></dt>
|
||
<dd class="field-even"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
|
||
<dt class="field-odd">Created<span class="colon">:</span></dt>
|
||
<dd class="field-odd">07-Dec-2003</dd>
|
||
<dt class="field-even">Post-History<span class="colon">:</span></dt>
|
||
<dd class="field-even">07-Dec-2003, 08-Aug-2004, 20-Aug-2004, 27-Aug-2004, 27-Sep-2010</dd>
|
||
<dt class="field-odd">Superseded-By<span class="colon">:</span></dt>
|
||
<dd class="field-odd"><a class="reference external" href="../pep-3333/">3333</a></dd>
|
||
</dl>
|
||
<hr class="docutils" />
|
||
<section id="contents">
|
||
<details><summary>Table of Contents</summary><ul class="simple">
|
||
<li><a class="reference internal" href="#preface">Preface</a></li>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#rationale-and-goals">Rationale and Goals</a></li>
|
||
<li><a class="reference internal" href="#specification-overview">Specification Overview</a><ul>
|
||
<li><a class="reference internal" href="#the-application-framework-side">The Application/Framework Side</a></li>
|
||
<li><a class="reference internal" href="#the-server-gateway-side">The Server/Gateway Side</a></li>
|
||
<li><a class="reference internal" href="#middleware-components-that-play-both-sides">Middleware: Components that Play Both Sides</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification-details">Specification Details</a><ul>
|
||
<li><a class="reference internal" href="#environ-variables"><code class="docutils literal notranslate"><span class="pre">environ</span></code> Variables</a><ul>
|
||
<li><a class="reference internal" href="#input-and-error-streams">Input and Error Streams</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#the-start-response-callable">The <code class="docutils literal notranslate"><span class="pre">start_response()</span></code> Callable</a><ul>
|
||
<li><a class="reference internal" href="#handling-the-content-length-header">Handling the <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> Header</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#buffering-and-streaming">Buffering and Streaming</a><ul>
|
||
<li><a class="reference internal" href="#middleware-handling-of-block-boundaries">Middleware Handling of Block Boundaries</a></li>
|
||
<li><a class="reference internal" href="#the-write-callable">The <code class="docutils literal notranslate"><span class="pre">write()</span></code> Callable</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#unicode-issues">Unicode Issues</a></li>
|
||
<li><a class="reference internal" href="#error-handling">Error Handling</a></li>
|
||
<li><a class="reference internal" href="#http-1-1-expect-continue">HTTP 1.1 Expect/Continue</a></li>
|
||
<li><a class="reference internal" href="#other-http-features">Other HTTP Features</a></li>
|
||
<li><a class="reference internal" href="#thread-support">Thread Support</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#implementation-application-notes">Implementation/Application Notes</a><ul>
|
||
<li><a class="reference internal" href="#server-extension-apis">Server Extension APIs</a></li>
|
||
<li><a class="reference internal" href="#application-configuration">Application Configuration</a></li>
|
||
<li><a class="reference internal" href="#url-reconstruction">URL Reconstruction</a></li>
|
||
<li><a class="reference internal" href="#supporting-older-2-2-versions-of-python">Supporting Older (<2.2) Versions of Python</a></li>
|
||
<li><a class="reference internal" href="#optional-platform-specific-file-handling">Optional Platform-Specific File Handling</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#questions-and-answers">Questions and Answers</a></li>
|
||
<li><a class="reference internal" href="#proposed-under-discussion">Proposed/Under Discussion</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
</details></section>
|
||
<section id="preface">
|
||
<h2><a class="toc-backref" href="#preface" role="doc-backlink">Preface</a></h2>
|
||
<p>Note: For an updated version of this spec that supports Python 3.x and
|
||
includes community errata, addenda, and clarifications, please
|
||
see <a class="pep reference internal" href="../pep-3333/" title="PEP 3333 – Python Web Server Gateway Interface v1.0.1">PEP 3333</a> instead.</p>
|
||
</section>
|
||
<section id="abstract">
|
||
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
||
<p>This document specifies a proposed standard interface between web
|
||
servers and Python web applications or frameworks, to promote web
|
||
application portability across a variety of web servers.</p>
|
||
</section>
|
||
<section id="rationale-and-goals">
|
||
<h2><a class="toc-backref" href="#rationale-and-goals" role="doc-backlink">Rationale and Goals</a></h2>
|
||
<p>Python currently boasts a wide variety of web application frameworks,
|
||
such as Zope, Quixote, Webware, SkunkWeb, PSO, and Twisted Web – to
|
||
name just a few <a class="footnote-reference brackets" href="#id4" id="id1">[1]</a>. This wide variety of choices can be a problem
|
||
for new Python users, because generally speaking, their choice of web
|
||
framework will limit their choice of usable web servers, and vice
|
||
versa.</p>
|
||
<p>By contrast, although Java has just as many web application frameworks
|
||
available, Java’s “servlet” API makes it possible for applications
|
||
written with any Java web application framework to run in any web
|
||
server that supports the servlet API.</p>
|
||
<p>The availability and widespread use of such an API in web servers for
|
||
Python – whether those servers are written in Python (e.g. Medusa),
|
||
embed Python (e.g. mod_python), or invoke Python via a gateway
|
||
protocol (e.g. CGI, FastCGI, etc.) – would separate choice of
|
||
framework from choice of web server, freeing users to choose a pairing
|
||
that suits them, while freeing framework and server developers to
|
||
focus on their preferred area of specialization.</p>
|
||
<p>This PEP, therefore, proposes a simple and universal interface between
|
||
web servers and web applications or frameworks: the Python Web Server
|
||
Gateway Interface (WSGI).</p>
|
||
<p>But the mere existence of a WSGI spec does nothing to address the
|
||
existing state of servers and frameworks for Python web applications.
|
||
Server and framework authors and maintainers must actually implement
|
||
WSGI for there to be any effect.</p>
|
||
<p>However, since no existing servers or frameworks support WSGI, there
|
||
is little immediate reward for an author who implements WSGI support.
|
||
Thus, WSGI <strong>must</strong> be easy to implement, so that an author’s initial
|
||
investment in the interface can be reasonably low.</p>
|
||
<p>Thus, simplicity of implementation on <em>both</em> the server and framework
|
||
sides of the interface is absolutely critical to the utility of the
|
||
WSGI interface, and is therefore the principal criterion for any
|
||
design decisions.</p>
|
||
<p>Note, however, that simplicity of implementation for a framework
|
||
author is not the same thing as ease of use for a web application
|
||
author. WSGI presents an absolutely “no frills” interface to the
|
||
framework author, because bells and whistles like response objects and
|
||
cookie handling would just get in the way of existing frameworks’
|
||
handling of these issues. Again, the goal of WSGI is to facilitate
|
||
easy interconnection of existing servers and applications or
|
||
frameworks, not to create a new web framework.</p>
|
||
<p>Note also that this goal precludes WSGI from requiring anything that
|
||
is not already available in deployed versions of Python. Therefore,
|
||
new standard library modules are not proposed or required by this
|
||
specification, and nothing in WSGI requires a Python version greater
|
||
than 2.2.2. (It would be a good idea, however, for future versions
|
||
of Python to include support for this interface in web servers
|
||
provided by the standard library.)</p>
|
||
<p>In addition to ease of implementation for existing and future
|
||
frameworks and servers, it should also be easy to create request
|
||
preprocessors, response postprocessors, and other WSGI-based
|
||
“middleware” components that look like an application to their
|
||
containing server, while acting as a server for their contained
|
||
applications.</p>
|
||
<p>If middleware can be both simple and robust, and WSGI is widely
|
||
available in servers and frameworks, it allows for the possibility
|
||
of an entirely new kind of Python web application framework: one
|
||
consisting of loosely-coupled WSGI middleware components. Indeed,
|
||
existing framework authors may even choose to refactor their
|
||
frameworks’ existing services to be provided in this way, becoming
|
||
more like libraries used with WSGI, and less like monolithic
|
||
frameworks. This would then allow application developers to choose
|
||
“best-of-breed” components for specific functionality, rather than
|
||
having to commit to all the pros and cons of a single framework.</p>
|
||
<p>Of course, as of this writing, that day is doubtless quite far off.
|
||
In the meantime, it is a sufficient short-term goal for WSGI to
|
||
enable the use of any framework with any server.</p>
|
||
<p>Finally, it should be mentioned that the current version of WSGI
|
||
does not prescribe any particular mechanism for “deploying” an
|
||
application for use with a web server or server gateway. At the
|
||
present time, this is necessarily implementation-defined by the
|
||
server or gateway. After a sufficient number of servers and
|
||
frameworks have implemented WSGI to provide field experience with
|
||
varying deployment requirements, it may make sense to create
|
||
another PEP, describing a deployment standard for WSGI servers and
|
||
application frameworks.</p>
|
||
</section>
|
||
<section id="specification-overview">
|
||
<h2><a class="toc-backref" href="#specification-overview" role="doc-backlink">Specification Overview</a></h2>
|
||
<p>The WSGI interface has two sides: the “server” or “gateway” side, and
|
||
the “application” or “framework” side. The server side invokes a
|
||
callable object that is provided by the application side. The
|
||
specifics of how that object is provided are up to the server or
|
||
gateway. It is assumed that some servers or gateways will require an
|
||
application’s deployer to write a short script to create an instance
|
||
of the server or gateway, and supply it with the application object.
|
||
Other servers and gateways may use configuration files or other
|
||
mechanisms to specify where an application object should be
|
||
imported from, or otherwise obtained.</p>
|
||
<p>In addition to “pure” servers/gateways and applications/frameworks,
|
||
it is also possible to create “middleware” components that implement
|
||
both sides of this specification. Such components act as an
|
||
application to their containing server, and as a server to a
|
||
contained application, and can be used to provide extended APIs,
|
||
content transformation, navigation, and other useful functions.</p>
|
||
<p>Throughout this specification, we will use the term “a callable” to
|
||
mean “a function, method, class, or an instance with a <code class="docutils literal notranslate"><span class="pre">__call__</span></code>
|
||
method”. It is up to the server, gateway, or application implementing
|
||
the callable to choose the appropriate implementation technique for
|
||
their needs. Conversely, a server, gateway, or application that is
|
||
invoking a callable <strong>must not</strong> have any dependency on what kind of
|
||
callable was provided to it. Callables are only to be called, not
|
||
introspected upon.</p>
|
||
<section id="the-application-framework-side">
|
||
<h3><a class="toc-backref" href="#the-application-framework-side" role="doc-backlink">The Application/Framework Side</a></h3>
|
||
<p>The application object is simply a callable object that accepts
|
||
two arguments. The term “object” should not be misconstrued as
|
||
requiring an actual object instance: a function, method, class,
|
||
or instance with a <code class="docutils literal notranslate"><span class="pre">__call__</span></code> method are all acceptable for
|
||
use as an application object. Application objects must be able
|
||
to be invoked more than once, as virtually all servers/gateways
|
||
(other than CGI) will make such repeated requests.</p>
|
||
<p>(Note: although we refer to it as an “application” object, this
|
||
should not be construed to mean that application developers will use
|
||
WSGI as a web programming API! It is assumed that application
|
||
developers will continue to use existing, high-level framework
|
||
services to develop their applications. WSGI is a tool for
|
||
framework and server developers, and is not intended to directly
|
||
support application developers.)</p>
|
||
<p>Here are two example application objects; one is a function, and the
|
||
other is a class:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">simple_app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Simplest possible application object"""</span>
|
||
<span class="n">status</span> <span class="o">=</span> <span class="s1">'200 OK'</span>
|
||
<span class="n">response_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">'Content-type'</span><span class="p">,</span> <span class="s1">'text/plain'</span><span class="p">)]</span>
|
||
<span class="n">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="p">[</span><span class="s1">'Hello world!</span><span class="se">\n</span><span class="s1">'</span><span class="p">]</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">AppClass</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="sd">"""Produce the same output, but using a class</span>
|
||
|
||
<span class="sd"> (Note: 'AppClass' is the "application" here, so calling it</span>
|
||
<span class="sd"> returns an instance of 'AppClass', which is then the iterable</span>
|
||
<span class="sd"> return value of the "application callable" as required by</span>
|
||
<span class="sd"> the spec.</span>
|
||
|
||
<span class="sd"> If we wanted to use *instances* of 'AppClass' as application</span>
|
||
<span class="sd"> objects instead, we would have to implement a '__call__'</span>
|
||
<span class="sd"> method, which would be invoked to execute the application,</span>
|
||
<span class="sd"> and we would need to create an instance for use by the</span>
|
||
<span class="sd"> server or gateway.</span>
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">environ</span> <span class="o">=</span> <span class="n">environ</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">start</span> <span class="o">=</span> <span class="n">start_response</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">status</span> <span class="o">=</span> <span class="s1">'200 OK'</span>
|
||
<span class="n">response_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">'Content-type'</span><span class="p">,</span> <span class="s1">'text/plain'</span><span class="p">)]</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span><span class="p">)</span>
|
||
<span class="k">yield</span> <span class="s2">"Hello world!</span><span class="se">\n</span><span class="s2">"</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="the-server-gateway-side">
|
||
<h3><a class="toc-backref" href="#the-server-gateway-side" role="doc-backlink">The Server/Gateway Side</a></h3>
|
||
<p>The server or gateway invokes the application callable once for each
|
||
request it receives from an HTTP client, that is directed at the
|
||
application. To illustrate, here is a simple CGI gateway, implemented
|
||
as a function taking an application object. Note that this simple
|
||
example has limited error handling, because by default an uncaught
|
||
exception will be dumped to <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code> and logged by the web
|
||
server.</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">sys</span>
|
||
|
||
<span class="k">def</span> <span class="nf">run_with_cgi</span><span class="p">(</span><span class="n">application</span><span class="p">):</span>
|
||
|
||
<span class="n">environ</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
|
||
<span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.input'</span><span class="p">]</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdin</span>
|
||
<span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.errors'</span><span class="p">]</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span>
|
||
<span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.version'</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.multithread'</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span>
|
||
<span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.multiprocess'</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
|
||
<span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.run_once'</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
|
||
|
||
<span class="k">if</span> <span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'HTTPS'</span><span class="p">,</span> <span class="s1">'off'</span><span class="p">)</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'on'</span><span class="p">,</span> <span class="s1">'1'</span><span class="p">):</span>
|
||
<span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.url_scheme'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'https'</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.url_scheme'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'http'</span>
|
||
|
||
<span class="n">headers_set</span> <span class="o">=</span> <span class="p">[]</span>
|
||
<span class="n">headers_sent</span> <span class="o">=</span> <span class="p">[]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">write</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">headers_set</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s2">"write() before start_response()"</span><span class="p">)</span>
|
||
|
||
<span class="k">elif</span> <span class="ow">not</span> <span class="n">headers_sent</span><span class="p">:</span>
|
||
<span class="c1"># Before the first output, send the stored headers</span>
|
||
<span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span> <span class="o">=</span> <span class="n">headers_sent</span><span class="p">[:]</span> <span class="o">=</span> <span class="n">headers_set</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'Status: </span><span class="si">%s</span><span class="se">\r\n</span><span class="s1">'</span> <span class="o">%</span> <span class="n">status</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="n">header</span> <span class="ow">in</span> <span class="n">response_headers</span><span class="p">:</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="si">%s</span><span class="s1">: </span><span class="si">%s</span><span class="se">\r\n</span><span class="s1">'</span> <span class="o">%</span> <span class="n">header</span><span class="p">)</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">'</span><span class="se">\r\n</span><span class="s1">'</span><span class="p">)</span>
|
||
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
|
||
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
|
||
|
||
<span class="k">def</span> <span class="nf">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span><span class="p">,</span> <span class="n">exc_info</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">exc_info</span><span class="p">:</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">headers_sent</span><span class="p">:</span>
|
||
<span class="c1"># Re-raise original exception if headers sent</span>
|
||
<span class="k">raise</span> <span class="n">exc_info</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">exc_info</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">exc_info</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||
<span class="k">finally</span><span class="p">:</span>
|
||
<span class="n">exc_info</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># avoid dangling circular ref</span>
|
||
<span class="k">elif</span> <span class="n">headers_set</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s2">"Headers already set!"</span><span class="p">)</span>
|
||
|
||
<span class="n">headers_set</span><span class="p">[:]</span> <span class="o">=</span> <span class="p">[</span><span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span><span class="p">]</span>
|
||
<span class="k">return</span> <span class="n">write</span>
|
||
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">application</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="k">for</span> <span class="n">data</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">data</span><span class="p">:</span> <span class="c1"># don't send headers until body appears</span>
|
||
<span class="n">write</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">headers_sent</span><span class="p">:</span>
|
||
<span class="n">write</span><span class="p">(</span><span class="s1">''</span><span class="p">)</span> <span class="c1"># send headers now if body was empty</span>
|
||
<span class="k">finally</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s1">'close'</span><span class="p">):</span>
|
||
<span class="n">result</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="middleware-components-that-play-both-sides">
|
||
<h3><a class="toc-backref" href="#middleware-components-that-play-both-sides" role="doc-backlink">Middleware: Components that Play Both Sides</a></h3>
|
||
<p>Note that a single object may play the role of a server with respect
|
||
to some application(s), while also acting as an application with
|
||
respect to some server(s). Such “middleware” components can perform
|
||
such functions as:</p>
|
||
<ul class="simple">
|
||
<li>Routing a request to different application objects based on the
|
||
target URL, after rewriting the <code class="docutils literal notranslate"><span class="pre">environ</span></code> accordingly.</li>
|
||
<li>Allowing multiple applications or frameworks to run side by side
|
||
in the same process</li>
|
||
<li>Load balancing and remote processing, by forwarding requests and
|
||
responses over a network</li>
|
||
<li>Perform content postprocessing, such as applying XSL stylesheets</li>
|
||
</ul>
|
||
<p>The presence of middleware in general is transparent to both the
|
||
“server/gateway” and the “application/framework” sides of the
|
||
interface, and should require no special support. A user who
|
||
desires to incorporate middleware into an application simply
|
||
provides the middleware component to the server, as if it were
|
||
an application, and configures the middleware component to
|
||
invoke the application, as if the middleware component were a
|
||
server. Of course, the “application” that the middleware wraps
|
||
may in fact be another middleware component wrapping another
|
||
application, and so on, creating what is referred to as a
|
||
“middleware stack”.</p>
|
||
<p>For the most part, middleware must conform to the restrictions
|
||
and requirements of both the server and application sides of
|
||
WSGI. In some cases, however, requirements for middleware
|
||
are more stringent than for a “pure” server or application,
|
||
and these points will be noted in the specification.</p>
|
||
<p>Here is a (tongue-in-cheek) example of a middleware component that
|
||
converts <code class="docutils literal notranslate"><span class="pre">text/plain</span></code> responses to pig Latin, using Joe Strout’s
|
||
<code class="docutils literal notranslate"><span class="pre">piglatin.py</span></code>. (Note: a “real” middleware component would
|
||
probably use a more robust way of checking the content type, and
|
||
should also check for a content encoding. Also, this simple
|
||
example ignores the possibility that a word might be split across
|
||
a block boundary.)</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">piglatin</span> <span class="kn">import</span> <span class="n">piglatin</span>
|
||
|
||
<span class="k">class</span> <span class="nc">LatinIter</span><span class="p">:</span>
|
||
|
||
<span class="w"> </span><span class="sd">"""Transform iterated output to piglatin, if it's okay to do so</span>
|
||
|
||
<span class="sd"> Note that the "okayness" can change until the application yields</span>
|
||
<span class="sd"> its first non-empty string, so 'transform_ok' has to be a mutable</span>
|
||
<span class="sd"> truth value.</span>
|
||
<span class="sd"> """</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="n">transform_ok</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s1">'close'</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">close</span> <span class="o">=</span> <span class="n">result</span><span class="o">.</span><span class="n">close</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_next</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">result</span><span class="p">)</span><span class="o">.</span><span class="n">next</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">transform_ok</span> <span class="o">=</span> <span class="n">transform_ok</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="bp">self</span>
|
||
|
||
<span class="k">def</span> <span class="nf">next</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">transform_ok</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">piglatin</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_next</span><span class="p">())</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_next</span><span class="p">()</span>
|
||
|
||
<span class="k">class</span> <span class="nc">Latinator</span><span class="p">:</span>
|
||
|
||
<span class="c1"># by default, don't transform output</span>
|
||
<span class="n">transform</span> <span class="o">=</span> <span class="kc">False</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">application</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">application</span> <span class="o">=</span> <span class="n">application</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
|
||
|
||
<span class="n">transform_ok</span> <span class="o">=</span> <span class="p">[]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">start_latin</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span><span class="p">,</span> <span class="n">exc_info</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
|
||
<span class="c1"># Reset ok flag, in case this is a repeat call</span>
|
||
<span class="k">del</span> <span class="n">transform_ok</span><span class="p">[:]</span>
|
||
|
||
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">response_headers</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'content-type'</span> <span class="ow">and</span> <span class="n">value</span> <span class="o">==</span> <span class="s1">'text/plain'</span><span class="p">:</span>
|
||
<span class="n">transform_ok</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
|
||
<span class="c1"># Strip content-length if present, else it'll be wrong</span>
|
||
<span class="n">response_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">response_headers</span>
|
||
<span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">!=</span> <span class="s1">'content-length'</span>
|
||
<span class="p">]</span>
|
||
<span class="k">break</span>
|
||
|
||
<span class="n">write</span> <span class="o">=</span> <span class="n">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span><span class="p">,</span> <span class="n">exc_info</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="n">transform_ok</span><span class="p">:</span>
|
||
<span class="k">def</span> <span class="nf">write_latin</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
|
||
<span class="n">write</span><span class="p">(</span><span class="n">piglatin</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
|
||
<span class="k">return</span> <span class="n">write_latin</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">write</span>
|
||
|
||
<span class="k">return</span> <span class="n">LatinIter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">application</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_latin</span><span class="p">),</span> <span class="n">transform_ok</span><span class="p">)</span>
|
||
|
||
|
||
<span class="c1"># Run foo_app under a Latinator's control, using the example CGI gateway</span>
|
||
<span class="kn">from</span> <span class="nn">foo_app</span> <span class="kn">import</span> <span class="n">foo_app</span>
|
||
<span class="n">run_with_cgi</span><span class="p">(</span><span class="n">Latinator</span><span class="p">(</span><span class="n">foo_app</span><span class="p">))</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="specification-details">
|
||
<h2><a class="toc-backref" href="#specification-details" role="doc-backlink">Specification Details</a></h2>
|
||
<p>The application object must accept two positional arguments. For
|
||
the sake of illustration, we have named them <code class="docutils literal notranslate"><span class="pre">environ</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">start_response</span></code>, but they are not required to have these names.
|
||
A server or gateway <strong>must</strong> invoke the application object using
|
||
positional (not keyword) arguments. (E.g. by calling
|
||
<code class="docutils literal notranslate"><span class="pre">result</span> <span class="pre">=</span> <span class="pre">application(environ,</span> <span class="pre">start_response)</span></code> as shown above.)</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">environ</span></code> parameter is a dictionary object, containing CGI-style
|
||
environment variables. This object <strong>must</strong> be a builtin Python
|
||
dictionary (<em>not</em> a subclass, <code class="docutils literal notranslate"><span class="pre">UserDict</span></code> or other dictionary
|
||
emulation), and the application is allowed to modify the dictionary
|
||
in any way it desires. The dictionary must also include certain
|
||
WSGI-required variables (described in a later section), and may
|
||
also include server-specific extension variables, named according
|
||
to a convention that will be described below.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">start_response</span></code> parameter is a callable accepting two
|
||
required positional arguments, and one optional argument. For the sake
|
||
of illustration, we have named these arguments <code class="docutils literal notranslate"><span class="pre">status</span></code>,
|
||
<code class="docutils literal notranslate"><span class="pre">response_headers</span></code>, and <code class="docutils literal notranslate"><span class="pre">exc_info</span></code>, but they are not required to
|
||
have these names, and the application <strong>must</strong> invoke the
|
||
<code class="docutils literal notranslate"><span class="pre">start_response</span></code> callable using positional arguments (e.g.
|
||
<code class="docutils literal notranslate"><span class="pre">start_response(status,</span> <span class="pre">response_headers)</span></code>).</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">status</span></code> parameter is a status string of the form
|
||
<code class="docutils literal notranslate"><span class="pre">"999</span> <span class="pre">Message</span> <span class="pre">here"</span></code>, and <code class="docutils literal notranslate"><span class="pre">response_headers</span></code> is a list of
|
||
<code class="docutils literal notranslate"><span class="pre">(header_name,</span> <span class="pre">header_value)</span></code> tuples describing the HTTP response
|
||
header. The optional <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> parameter is described below in the
|
||
sections on <a class="reference internal" href="#the-start-response-callable">The start_response() Callable</a> and <a class="reference internal" href="#error-handling">Error Handling</a>.
|
||
It is used only when the application has trapped an error and is
|
||
attempting to display an error message to the browser.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">start_response</span></code> callable must return a <code class="docutils literal notranslate"><span class="pre">write(body_data)</span></code>
|
||
callable that takes one positional parameter: a string to be written
|
||
as part of the HTTP response body. (Note: the <code class="docutils literal notranslate"><span class="pre">write()</span></code> callable is
|
||
provided only to support certain existing frameworks’ imperative output
|
||
APIs; it should not be used by new applications or frameworks if it
|
||
can be avoided. See the <a class="reference internal" href="#buffering-and-streaming">Buffering and Streaming</a> section for more
|
||
details.)</p>
|
||
<p>When called by the server, the application object must return an
|
||
iterable yielding zero or more strings. This can be accomplished in a
|
||
variety of ways, such as by returning a list of strings, or by the
|
||
application being a generator function that yields strings, or
|
||
by the application being a class whose instances are iterable.
|
||
Regardless of how it is accomplished, the application object must
|
||
always return an iterable yielding zero or more strings.</p>
|
||
<p>The server or gateway must transmit the yielded strings to the client
|
||
in an unbuffered fashion, completing the transmission of each string
|
||
before requesting another one. (In other words, applications
|
||
<strong>should</strong> perform their own buffering. See the <a class="reference internal" href="#buffering-and-streaming">Buffering and
|
||
Streaming</a> section below for more on how application output must be
|
||
handled.)</p>
|
||
<p>The server or gateway should treat the yielded strings as binary byte
|
||
sequences: in particular, it should ensure that line endings are
|
||
not altered. The application is responsible for ensuring that the
|
||
string(s) to be written are in a format suitable for the client. (The
|
||
server or gateway <strong>may</strong> apply HTTP transfer encodings, or perform
|
||
other transformations for the purpose of implementing HTTP features
|
||
such as byte-range transmission. See <a class="reference internal" href="#other-http-features">Other HTTP Features</a>, below,
|
||
for more details.)</p>
|
||
<p>If a call to <code class="docutils literal notranslate"><span class="pre">len(iterable)</span></code> succeeds, the server must be able
|
||
to rely on the result being accurate. That is, if the iterable
|
||
returned by the application provides a working <code class="docutils literal notranslate"><span class="pre">__len__()</span></code>
|
||
method, it <strong>must</strong> return an accurate result. (See
|
||
the <a class="reference internal" href="#handling-the-content-length-header">Handling the Content-Length Header</a> section for information
|
||
on how this would normally be used.)</p>
|
||
<p>If the iterable returned by the application has a <code class="docutils literal notranslate"><span class="pre">close()</span></code> method,
|
||
the server or gateway <strong>must</strong> call that method upon completion of the
|
||
current request, whether the request was completed normally, or
|
||
terminated early due to an error (this is to support resource release
|
||
by the application). This protocol is intended to complement <a class="pep reference internal" href="../pep-0325/" title="PEP 325 – Resource-Release Support for Generators">PEP 325</a>’s
|
||
generator support, and other common iterables with <code class="docutils literal notranslate"><span class="pre">close()</span></code> methods.</p>
|
||
<p>(Note: the application <strong>must</strong> invoke the <code class="docutils literal notranslate"><span class="pre">start_response()</span></code>
|
||
callable before the iterable yields its first body string, so that the
|
||
server can send the headers before any body content. However, this
|
||
invocation <strong>may</strong> be performed by the iterable’s first iteration, so
|
||
servers <strong>must not</strong> assume that <code class="docutils literal notranslate"><span class="pre">start_response()</span></code> has been called
|
||
before they begin iterating over the iterable.)</p>
|
||
<p>Finally, servers and gateways <strong>must not</strong> directly use any other
|
||
attributes of the iterable returned by the application, unless it is an
|
||
instance of a type specific to that server or gateway, such as a “file
|
||
wrapper” returned by <code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code> (see <a class="reference internal" href="#optional-platform-specific-file-handling">Optional
|
||
Platform-Specific File Handling</a>). In the general case, only
|
||
attributes specified here, or accessed via e.g. the <a class="pep reference internal" href="../pep-0234/" title="PEP 234 – Iterators">PEP 234</a> iteration
|
||
APIs are acceptable.</p>
|
||
<section id="environ-variables">
|
||
<h3><a class="toc-backref" href="#environ-variables" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">environ</span></code> Variables</a></h3>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">environ</span></code> dictionary is required to contain these CGI
|
||
environment variables, as defined by the Common Gateway Interface
|
||
specification <a class="footnote-reference brackets" href="#id5" id="id2">[2]</a>. The following variables <strong>must</strong> be present,
|
||
unless their value would be an empty string, in which case they
|
||
<strong>may</strong> be omitted, except as otherwise noted below.</p>
|
||
<dl class="simple">
|
||
<dt><code class="docutils literal notranslate"><span class="pre">REQUEST_METHOD</span></code></dt><dd>The HTTP request method, such as <code class="docutils literal notranslate"><span class="pre">"GET"</span></code> or <code class="docutils literal notranslate"><span class="pre">"POST"</span></code>. This
|
||
cannot ever be an empty string, and so is always required.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">SCRIPT_NAME</span></code></dt><dd>The initial portion of the request URL’s “path” that corresponds to
|
||
the application object, so that the application knows its virtual
|
||
“location”. This <strong>may</strong> be an empty string, if the application
|
||
corresponds to the “root” of the server.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">PATH_INFO</span></code></dt><dd>The remainder of the request URL’s “path”, designating the virtual
|
||
“location” of the request’s target within the application. This
|
||
<strong>may</strong> be an empty string, if the request URL targets the
|
||
application root and does not have a trailing slash.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">QUERY_STRING</span></code></dt><dd>The portion of the request URL that follows the <code class="docutils literal notranslate"><span class="pre">"?"</span></code>, if any.
|
||
May be empty or absent.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">CONTENT_TYPE</span></code></dt><dd>The contents of any <code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> fields in the HTTP request.
|
||
May be empty or absent.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">CONTENT_LENGTH</span></code></dt><dd>The contents of any <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> fields in the HTTP request.
|
||
May be empty or absent.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">SERVER_NAME</span></code>, <code class="docutils literal notranslate"><span class="pre">SERVER_PORT</span></code></dt><dd>When combined with <code class="docutils literal notranslate"><span class="pre">SCRIPT_NAME</span></code> and <code class="docutils literal notranslate"><span class="pre">PATH_INFO</span></code>, these variables
|
||
can be used to complete the URL. Note, however, that <code class="docutils literal notranslate"><span class="pre">HTTP_HOST</span></code>,
|
||
if present, should be used in preference to <code class="docutils literal notranslate"><span class="pre">SERVER_NAME</span></code> for
|
||
reconstructing the request URL. See the <a class="reference internal" href="#url-reconstruction">URL Reconstruction</a>
|
||
section below for more detail. <code class="docutils literal notranslate"><span class="pre">SERVER_NAME</span></code> and <code class="docutils literal notranslate"><span class="pre">SERVER_PORT</span></code>
|
||
can never be empty strings, and so are always required.</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">SERVER_PROTOCOL</span></code></dt><dd>The version of the protocol the client used to send the request.
|
||
Typically this will be something like <code class="docutils literal notranslate"><span class="pre">"HTTP/1.0"</span></code> or <code class="docutils literal notranslate"><span class="pre">"HTTP/1.1"</span></code>
|
||
and may be used by the application to determine how to treat any
|
||
HTTP request headers. (This variable should probably be called
|
||
<code class="docutils literal notranslate"><span class="pre">REQUEST_PROTOCOL</span></code>, since it denotes the protocol used in the
|
||
request, and is not necessarily the protocol that will be used in the
|
||
server’s response. However, for compatibility with CGI we have to
|
||
keep the existing name.)</dd>
|
||
<dt><code class="docutils literal notranslate"><span class="pre">HTTP_</span></code> Variables</dt><dd>Variables corresponding to the client-supplied HTTP request headers
|
||
(i.e., variables whose names begin with <code class="docutils literal notranslate"><span class="pre">"HTTP_"</span></code>). The presence or
|
||
absence of these variables should correspond with the presence or
|
||
absence of the appropriate HTTP header in the request.</dd>
|
||
</dl>
|
||
<p>A server or gateway <strong>should</strong> attempt to provide as many other CGI
|
||
variables as are applicable. In addition, if SSL is in use, the server
|
||
or gateway <strong>should</strong> also provide as many of the Apache SSL environment
|
||
variables <a class="footnote-reference brackets" href="#id6" id="id3">[3]</a> as are applicable, such as <code class="docutils literal notranslate"><span class="pre">HTTPS=on</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">SSL_PROTOCOL</span></code>. Note, however, that an application that uses any CGI
|
||
variables other than the ones listed above are necessarily non-portable
|
||
to web servers that do not support the relevant extensions. (For
|
||
example, web servers that do not publish files will not be able to
|
||
provide a meaningful <code class="docutils literal notranslate"><span class="pre">DOCUMENT_ROOT</span></code> or <code class="docutils literal notranslate"><span class="pre">PATH_TRANSLATED</span></code>.)</p>
|
||
<p>A WSGI-compliant server or gateway <strong>should</strong> document what variables
|
||
it provides, along with their definitions as appropriate. Applications
|
||
<strong>should</strong> check for the presence of any variables they require, and
|
||
have a fallback plan in the event such a variable is absent.</p>
|
||
<p>Note: missing variables (such as <code class="docutils literal notranslate"><span class="pre">REMOTE_USER</span></code> when no
|
||
authentication has occurred) should be left out of the <code class="docutils literal notranslate"><span class="pre">environ</span></code>
|
||
dictionary. Also note that CGI-defined variables must be strings,
|
||
if they are present at all. It is a violation of this specification
|
||
for a CGI variable’s value to be of any type other than <code class="docutils literal notranslate"><span class="pre">str</span></code>.</p>
|
||
<p>In addition to the CGI-defined variables, the <code class="docutils literal notranslate"><span class="pre">environ</span></code> dictionary
|
||
<strong>may</strong> also contain arbitrary operating-system “environment variables”,
|
||
and <strong>must</strong> contain the following WSGI-defined variables:</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head">Variable</th>
|
||
<th class="head">Value</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">wsgi.version</span></code></td>
|
||
<td>The tuple <code class="docutils literal notranslate"><span class="pre">(1,</span> <span class="pre">0)</span></code>, representing WSGI
|
||
version 1.0.</td>
|
||
</tr>
|
||
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">wsgi.url_scheme</span></code></td>
|
||
<td>A string representing the “scheme” portion of
|
||
the URL at which the application is being
|
||
invoked. Normally, this will have the value
|
||
<code class="docutils literal notranslate"><span class="pre">"http"</span></code> or <code class="docutils literal notranslate"><span class="pre">"https"</span></code>, as appropriate.</td>
|
||
</tr>
|
||
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">wsgi.input</span></code></td>
|
||
<td>An input stream (file-like object) from which
|
||
the HTTP request body can be read. (The server
|
||
or gateway may perform reads on-demand as
|
||
requested by the application, or it may
|
||
pre-read the client’s request body and buffer
|
||
it in-memory or on disk, or use any other
|
||
technique for providing such an input stream,
|
||
according to its preference.)</td>
|
||
</tr>
|
||
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">wsgi.errors</span></code></td>
|
||
<td>An output stream (file-like object) to which
|
||
error output can be written, for the purpose of
|
||
recording program or other errors in a
|
||
standardized and possibly centralized location.
|
||
This should be a “text mode” stream; i.e.,
|
||
applications should use <code class="docutils literal notranslate"><span class="pre">"\n"</span></code> as a line
|
||
ending, and assume that it will be converted to
|
||
the correct line ending by the server/gateway.<p>For many servers, <code class="docutils literal notranslate"><span class="pre">wsgi.errors</span></code> will be the
|
||
server’s main error log. Alternatively, this
|
||
may be <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code>, or a log file of some
|
||
sort. The server’s documentation should
|
||
include an explanation of how to configure this
|
||
or where to find the recorded output. A server
|
||
or gateway may supply different error streams
|
||
to different applications, if this is desired.</p>
|
||
</td>
|
||
</tr>
|
||
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">wsgi.multithread</span></code></td>
|
||
<td>This value should evaluate true if the
|
||
application object may be simultaneously
|
||
invoked by another thread in the same process,
|
||
and should evaluate false otherwise.</td>
|
||
</tr>
|
||
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">wsgi.multiprocess</span></code></td>
|
||
<td>This value should evaluate true if an
|
||
equivalent application object may be
|
||
simultaneously invoked by another process,
|
||
and should evaluate false otherwise.</td>
|
||
</tr>
|
||
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">wsgi.run_once</span></code></td>
|
||
<td>This value should evaluate true if the server
|
||
or gateway expects (but does not guarantee!)
|
||
that the application will only be invoked this
|
||
one time during the life of its containing
|
||
process. Normally, this will only be true for
|
||
a gateway based on CGI (or something similar).</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Finally, the <code class="docutils literal notranslate"><span class="pre">environ</span></code> dictionary may also contain server-defined
|
||
variables. These variables should be named using only lower-case
|
||
letters, numbers, dots, and underscores, and should be prefixed with
|
||
a name that is unique to the defining server or gateway. For
|
||
example, <code class="docutils literal notranslate"><span class="pre">mod_python</span></code> might define variables with names like
|
||
<code class="docutils literal notranslate"><span class="pre">mod_python.some_variable</span></code>.</p>
|
||
<section id="input-and-error-streams">
|
||
<h4><a class="toc-backref" href="#input-and-error-streams" role="doc-backlink">Input and Error Streams</a></h4>
|
||
<p>The input and error streams provided by the server must support
|
||
the following methods:</p>
|
||
<table class="docutils align-default">
|
||
<thead>
|
||
<tr class="row-odd"><th class="head">Method</th>
|
||
<th class="head">Stream</th>
|
||
<th class="head">Notes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">read(size)</span></code></td>
|
||
<td><code class="docutils literal notranslate"><span class="pre">input</span></code></td>
|
||
<td>1</td>
|
||
</tr>
|
||
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">readline()</span></code></td>
|
||
<td><code class="docutils literal notranslate"><span class="pre">input</span></code></td>
|
||
<td>1, 2</td>
|
||
</tr>
|
||
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">readlines(hint)</span></code></td>
|
||
<td><code class="docutils literal notranslate"><span class="pre">input</span></code></td>
|
||
<td>1, 3</td>
|
||
</tr>
|
||
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">__iter__()</span></code></td>
|
||
<td><code class="docutils literal notranslate"><span class="pre">input</span></code></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">flush()</span></code></td>
|
||
<td><code class="docutils literal notranslate"><span class="pre">errors</span></code></td>
|
||
<td>4</td>
|
||
</tr>
|
||
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">write(str)</span></code></td>
|
||
<td><code class="docutils literal notranslate"><span class="pre">errors</span></code></td>
|
||
<td></td>
|
||
</tr>
|
||
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">writelines(seq)</span></code></td>
|
||
<td><code class="docutils literal notranslate"><span class="pre">errors</span></code></td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>The semantics of each method are as documented in the Python Library
|
||
Reference, except for these notes as listed in the table above:</p>
|
||
<ol class="arabic simple">
|
||
<li>The server is not required to read past the client’s specified
|
||
<code class="docutils literal notranslate"><span class="pre">Content-Length</span></code>, and is allowed to simulate an end-of-file
|
||
condition if the application attempts to read past that point.
|
||
The application <strong>should not</strong> attempt to read more data than is
|
||
specified by the <code class="docutils literal notranslate"><span class="pre">CONTENT_LENGTH</span></code> variable.</li>
|
||
<li>The optional “size” argument to <code class="docutils literal notranslate"><span class="pre">readline()</span></code> is not supported,
|
||
as it may be complex for server authors to implement, and is not
|
||
often used in practice.</li>
|
||
<li>Note that the <code class="docutils literal notranslate"><span class="pre">hint</span></code> argument to <code class="docutils literal notranslate"><span class="pre">readlines()</span></code> is optional for
|
||
both caller and implementer. The application is free not to
|
||
supply it, and the server or gateway is free to ignore it.</li>
|
||
<li>Since the <code class="docutils literal notranslate"><span class="pre">errors</span></code> stream may not be rewound, servers and gateways
|
||
are free to forward write operations immediately, without buffering.
|
||
In this case, the <code class="docutils literal notranslate"><span class="pre">flush()</span></code> method may be a no-op. Portable
|
||
applications, however, cannot assume that output is unbuffered
|
||
or that <code class="docutils literal notranslate"><span class="pre">flush()</span></code> is a no-op. They must call <code class="docutils literal notranslate"><span class="pre">flush()</span></code> if
|
||
they need to ensure that output has in fact been written. (For
|
||
example, to minimize intermingling of data from multiple processes
|
||
writing to the same error log.)</li>
|
||
</ol>
|
||
<p>The methods listed in the table above <strong>must</strong> be supported by all
|
||
servers conforming to this specification. Applications conforming
|
||
to this specification <strong>must not</strong> use any other methods or attributes
|
||
of the <code class="docutils literal notranslate"><span class="pre">input</span></code> or <code class="docutils literal notranslate"><span class="pre">errors</span></code> objects. In particular, applications
|
||
<strong>must not</strong> attempt to close these streams, even if they possess
|
||
<code class="docutils literal notranslate"><span class="pre">close()</span></code> methods.</p>
|
||
</section>
|
||
</section>
|
||
<section id="the-start-response-callable">
|
||
<h3><a class="toc-backref" href="#the-start-response-callable" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">start_response()</span></code> Callable</a></h3>
|
||
<p>The second parameter passed to the application object is a callable
|
||
of the form <code class="docutils literal notranslate"><span class="pre">start_response(status,</span> <span class="pre">response_headers,</span> <span class="pre">exc_info=None)</span></code>.
|
||
(As with all WSGI callables, the arguments must be supplied
|
||
positionally, not by keyword.) The <code class="docutils literal notranslate"><span class="pre">start_response</span></code> callable is
|
||
used to begin the HTTP response, and it must return a
|
||
<code class="docutils literal notranslate"><span class="pre">write(body_data)</span></code> callable (see the <a class="reference internal" href="#buffering-and-streaming">Buffering and Streaming</a>
|
||
section, below).</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">status</span></code> argument is an HTTP “status” string 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>. That is, it is a string consisting of a
|
||
Status-Code and a Reason-Phrase, in that order and separated by a
|
||
single space, with no surrounding whitespace or other characters.
|
||
(See <span class="target" id="index-0"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a>, Section 6.1.1 for more information.) The string
|
||
<strong>must not</strong> contain control characters, and must not be terminated
|
||
with a carriage return, linefeed, or combination thereof.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">response_headers</span></code> argument is a list of <code class="docutils literal notranslate"><span class="pre">(header_name,</span>
|
||
<span class="pre">header_value)</span></code> tuples. It must be a Python list; i.e.
|
||
<code class="docutils literal notranslate"><span class="pre">type(response_headers)</span> <span class="pre">is</span> <span class="pre">ListType</span></code>, and the server <strong>may</strong> change
|
||
its contents in any way it desires. Each <code class="docutils literal notranslate"><span class="pre">header_name</span></code> must be a
|
||
valid HTTP header field-name (as defined by <span class="target" id="index-1"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a>, Section 4.2),
|
||
without a trailing colon or other punctuation.</p>
|
||
<p>Each <code class="docutils literal notranslate"><span class="pre">header_value</span></code> <strong>must not</strong> include <em>any</em> control characters,
|
||
including carriage returns or linefeeds, either embedded or at the end.
|
||
(These requirements are to minimize the complexity of any parsing that
|
||
must be performed by servers, gateways, and intermediate response
|
||
processors that need to inspect or modify response headers.)</p>
|
||
<p>In general, the server or gateway is responsible for ensuring that
|
||
correct headers are sent to the client: if the application omits
|
||
a header required by HTTP (or other relevant specifications that are in
|
||
effect), the server or gateway <strong>must</strong> add it. For example, the HTTP
|
||
<code class="docutils literal notranslate"><span class="pre">Date:</span></code> and <code class="docutils literal notranslate"><span class="pre">Server:</span></code> headers would normally be supplied by the
|
||
server or gateway.</p>
|
||
<p>(A reminder for server/gateway authors: HTTP header names are
|
||
case-insensitive, so be sure to take that into consideration when
|
||
examining application-supplied headers!)</p>
|
||
<p>Applications and middleware are forbidden from using HTTP/1.1
|
||
“hop-by-hop” features or headers, any equivalent features in HTTP/1.0,
|
||
or any headers that would affect the persistence of the client’s
|
||
connection to the web server. These features are the
|
||
exclusive province of the actual web server, and a server or gateway
|
||
<strong>should</strong> consider it a fatal error for an application to attempt
|
||
sending them, and raise an error if they are supplied to
|
||
<code class="docutils literal notranslate"><span class="pre">start_response()</span></code>. (For more specifics on “hop-by-hop” features and
|
||
headers, please see the <a class="reference internal" href="#other-http-features">Other HTTP Features</a> section below.)</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">start_response</span></code> callable <strong>must not</strong> actually transmit the
|
||
response headers. Instead, it must store them for the server or
|
||
gateway to transmit <strong>only</strong> after the first iteration of the
|
||
application return value that yields a non-empty string, or upon
|
||
the application’s first invocation of the <code class="docutils literal notranslate"><span class="pre">write()</span></code> callable. In
|
||
other words, response headers must not be sent until there is actual
|
||
body data available, or until the application’s returned iterable is
|
||
exhausted. (The only possible exception to this rule is if the
|
||
response headers explicitly include a <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> of zero.)</p>
|
||
<p>This delaying of response header transmission is to ensure that buffered
|
||
and asynchronous applications can replace their originally intended
|
||
output with error output, up until the last possible moment. For
|
||
example, the application may need to change the response status from
|
||
“200 OK” to “500 Internal Error”, if an error occurs while the body is
|
||
being generated within an application buffer.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> argument, if supplied, must be a Python
|
||
<code class="docutils literal notranslate"><span class="pre">sys.exc_info()</span></code> tuple. This argument should be supplied by the
|
||
application only if <code class="docutils literal notranslate"><span class="pre">start_response</span></code> is being called by an error
|
||
handler. If <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> is supplied, and no HTTP headers have been
|
||
output yet, <code class="docutils literal notranslate"><span class="pre">start_response</span></code> should replace the currently-stored
|
||
HTTP response headers with the newly-supplied ones, thus allowing the
|
||
application to “change its mind” about the output when an error has
|
||
occurred.</p>
|
||
<p>However, if <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> is provided, and the HTTP headers have already
|
||
been sent, <code class="docutils literal notranslate"><span class="pre">start_response</span></code> <strong>must</strong> raise an error, and <strong>should</strong>
|
||
raise the <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> tuple. That is:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">raise</span> <span class="n">exc_info</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">exc_info</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">exc_info</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>This will re-raise the exception trapped by the application, and in
|
||
principle should abort the application. (It is not safe for the
|
||
application to attempt error output to the browser once the HTTP
|
||
headers have already been sent.) The application <strong>must not</strong> trap
|
||
any exceptions raised by <code class="docutils literal notranslate"><span class="pre">start_response</span></code>, if it called
|
||
<code class="docutils literal notranslate"><span class="pre">start_response</span></code> with <code class="docutils literal notranslate"><span class="pre">exc_info</span></code>. Instead, it should allow
|
||
such exceptions to propagate back to the server or gateway. See
|
||
<a class="reference internal" href="#error-handling">Error Handling</a> below, for more details.</p>
|
||
<p>The application <strong>may</strong> call <code class="docutils literal notranslate"><span class="pre">start_response</span></code> more than once, if and
|
||
only if the <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> argument is provided. More precisely, it is
|
||
a fatal error to call <code class="docutils literal notranslate"><span class="pre">start_response</span></code> without the <code class="docutils literal notranslate"><span class="pre">exc_info</span></code>
|
||
argument if <code class="docutils literal notranslate"><span class="pre">start_response</span></code> has already been called within the
|
||
current invocation of the application. (See the example CGI
|
||
gateway above for an illustration of the correct logic.)</p>
|
||
<p>Note: servers, gateways, or middleware implementing <code class="docutils literal notranslate"><span class="pre">start_response</span></code>
|
||
<strong>should</strong> ensure that no reference is held to the <code class="docutils literal notranslate"><span class="pre">exc_info</span></code>
|
||
parameter beyond the duration of the function’s execution, to avoid
|
||
creating a circular reference through the traceback and frames
|
||
involved. The simplest way to do this is something like:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span><span class="p">,</span> <span class="n">exc_info</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="n">exc_info</span><span class="p">:</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="c1"># do stuff w/exc_info here</span>
|
||
<span class="k">finally</span><span class="p">:</span>
|
||
<span class="n">exc_info</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Avoid circular ref.</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The example CGI gateway provides another illustration of this
|
||
technique.</p>
|
||
<section id="handling-the-content-length-header">
|
||
<h4><a class="toc-backref" href="#handling-the-content-length-header" role="doc-backlink">Handling the <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> Header</a></h4>
|
||
<p>If the application does not supply a <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> header, a
|
||
server or gateway may choose one of several approaches to handling
|
||
it. The simplest of these is to close the client connection when
|
||
the response is completed.</p>
|
||
<p>Under some circumstances, however, the server or gateway may be
|
||
able to either generate a <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> header, or at least
|
||
avoid the need to close the client connection. If the application
|
||
does <em>not</em> call the <code class="docutils literal notranslate"><span class="pre">write()</span></code> callable, and returns an iterable
|
||
whose <code class="docutils literal notranslate"><span class="pre">len()</span></code> is 1, then the server can automatically determine
|
||
<code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> by taking the length of the first string yielded
|
||
by the iterable.</p>
|
||
<p>And, if the server and client both support HTTP/1.1
|
||
<span class="target" id="index-2"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html#section-3.6.1"><strong>“chunked encoding”</strong></a>,
|
||
then the server <strong>may</strong> use chunked encoding to send
|
||
a chunk for each <code class="docutils literal notranslate"><span class="pre">write()</span></code> call or string yielded by the iterable,
|
||
thus generating a <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> header for each chunk. This
|
||
allows the server to keep the client connection alive, if it wishes
|
||
to do so. Note that the server <strong>must</strong> comply fully with <span class="target" id="index-3"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a>
|
||
when doing this, or else fall back to one of the other strategies for
|
||
dealing with the absence of <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code>.</p>
|
||
<p>(Note: applications and middleware <strong>must not</strong> apply any kind of
|
||
<code class="docutils literal notranslate"><span class="pre">Transfer-Encoding</span></code> to their output, such as chunking or gzipping;
|
||
as “hop-by-hop” operations, these encodings are the province of the
|
||
actual web server/gateway. See <a class="reference internal" href="#other-http-features">Other HTTP Features</a> below, for
|
||
more details.)</p>
|
||
</section>
|
||
</section>
|
||
<section id="buffering-and-streaming">
|
||
<h3><a class="toc-backref" href="#buffering-and-streaming" role="doc-backlink">Buffering and Streaming</a></h3>
|
||
<p>Generally speaking, applications will achieve the best throughput
|
||
by buffering their (modestly-sized) output and sending it all at
|
||
once. This is a common approach in existing frameworks such as
|
||
Zope: the output is buffered in a StringIO or similar object, then
|
||
transmitted all at once, along with the response headers.</p>
|
||
<p>The corresponding approach in WSGI is for the application to simply
|
||
return a single-element iterable (such as a list) containing the
|
||
response body as a single string. This is the recommended approach
|
||
for the vast majority of application functions, that render
|
||
HTML pages whose text easily fits in memory.</p>
|
||
<p>For large files, however, or for specialized uses of HTTP streaming
|
||
(such as multipart “server push”), an application may need to provide
|
||
output in smaller blocks (e.g. to avoid loading a large file into
|
||
memory). It’s also sometimes the case that part of a response may
|
||
be time-consuming to produce, but it would be useful to send ahead the
|
||
portion of the response that precedes it.</p>
|
||
<p>In these cases, applications will usually return an iterator (often
|
||
a generator-iterator) that produces the output in a block-by-block
|
||
fashion. These blocks may be broken to coincide with multipart
|
||
boundaries (for “server push”), or just before time-consuming
|
||
tasks (such as reading another block of an on-disk file).</p>
|
||
<p>WSGI servers, gateways, and middleware <strong>must not</strong> delay the
|
||
transmission of any block; they <strong>must</strong> either fully transmit
|
||
the block to the client, or guarantee that they will continue
|
||
transmission even while the application is producing its next block.
|
||
A server/gateway or middleware may provide this guarantee in one of
|
||
three ways:</p>
|
||
<ol class="arabic simple">
|
||
<li>Send the entire block to the operating system (and request
|
||
that any O/S buffers be flushed) before returning control
|
||
to the application, OR</li>
|
||
<li>Use a different thread to ensure that the block continues
|
||
to be transmitted while the application produces the next
|
||
block.</li>
|
||
<li>(Middleware only) send the entire block to its parent
|
||
gateway/server</li>
|
||
</ol>
|
||
<p>By providing this guarantee, WSGI allows applications to ensure
|
||
that transmission will not become stalled at an arbitrary point
|
||
in their output data. This is critical for proper functioning
|
||
of e.g. multipart “server push” streaming, where data between
|
||
multipart boundaries should be transmitted in full to the client.</p>
|
||
<section id="middleware-handling-of-block-boundaries">
|
||
<h4><a class="toc-backref" href="#middleware-handling-of-block-boundaries" role="doc-backlink">Middleware Handling of Block Boundaries</a></h4>
|
||
<p>In order to better support asynchronous applications and servers,
|
||
middleware components <strong>must not</strong> block iteration waiting for
|
||
multiple values from an application iterable. If the middleware
|
||
needs to accumulate more data from the application before it can
|
||
produce any output, it <strong>must</strong> yield an empty string.</p>
|
||
<p>To put this requirement another way, a middleware component <strong>must
|
||
yield at least one value</strong> each time its underlying application
|
||
yields a value. If the middleware cannot yield any other value,
|
||
it must yield an empty string.</p>
|
||
<p>This requirement ensures that asynchronous applications and servers
|
||
can conspire to reduce the number of threads that are required
|
||
to run a given number of application instances simultaneously.</p>
|
||
<p>Note also that this requirement means that middleware <strong>must</strong>
|
||
return an iterable as soon as its underlying application returns
|
||
an iterable. It is also forbidden for middleware to use the
|
||
<code class="docutils literal notranslate"><span class="pre">write()</span></code> callable to transmit data that is yielded by an
|
||
underlying application. Middleware may only use their parent
|
||
server’s <code class="docutils literal notranslate"><span class="pre">write()</span></code> callable to transmit data that the
|
||
underlying application sent using a middleware-provided <code class="docutils literal notranslate"><span class="pre">write()</span></code>
|
||
callable.</p>
|
||
</section>
|
||
<section id="the-write-callable">
|
||
<h4><a class="toc-backref" href="#the-write-callable" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">write()</span></code> Callable</a></h4>
|
||
<p>Some existing application framework APIs support unbuffered
|
||
output in a different manner than WSGI. Specifically, they
|
||
provide a “write” function or method of some kind to write
|
||
an unbuffered block of data, or else they provide a buffered
|
||
“write” function and a “flush” mechanism to flush the buffer.</p>
|
||
<p>Unfortunately, such APIs cannot be implemented in terms of
|
||
WSGI’s “iterable” application return value, unless threads
|
||
or other special mechanisms are used.</p>
|
||
<p>Therefore, to allow these frameworks to continue using an
|
||
imperative API, WSGI includes a special <code class="docutils literal notranslate"><span class="pre">write()</span></code> callable,
|
||
returned by the <code class="docutils literal notranslate"><span class="pre">start_response</span></code> callable.</p>
|
||
<p>New WSGI applications and frameworks <strong>should not</strong> use the
|
||
<code class="docutils literal notranslate"><span class="pre">write()</span></code> callable if it is possible to avoid doing so. The
|
||
<code class="docutils literal notranslate"><span class="pre">write()</span></code> callable is strictly a hack to support imperative
|
||
streaming APIs. In general, applications should produce their
|
||
output via their returned iterable, as this makes it possible
|
||
for web servers to interleave other tasks in the same Python thread,
|
||
potentially providing better throughput for the server as a whole.</p>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">write()</span></code> callable is returned by the <code class="docutils literal notranslate"><span class="pre">start_response()</span></code>
|
||
callable, and it accepts a single parameter: a string to be
|
||
written as part of the HTTP response body, that is treated exactly
|
||
as though it had been yielded by the output iterable. In other
|
||
words, before <code class="docutils literal notranslate"><span class="pre">write()</span></code> returns, it must guarantee that the
|
||
passed-in string was either completely sent to the client, or
|
||
that it is buffered for transmission while the application
|
||
proceeds onward.</p>
|
||
<p>An application <strong>must</strong> return an iterable object, even if it
|
||
uses <code class="docutils literal notranslate"><span class="pre">write()</span></code> to produce all or part of its response body.
|
||
The returned iterable <strong>may</strong> be empty (i.e. yield no non-empty
|
||
strings), but if it <em>does</em> yield non-empty strings, that output
|
||
must be treated normally by the server or gateway (i.e., it must be
|
||
sent or queued immediately). Applications <strong>must not</strong> invoke
|
||
<code class="docutils literal notranslate"><span class="pre">write()</span></code> from within their return iterable, and therefore any
|
||
strings yielded by the iterable are transmitted after all strings
|
||
passed to <code class="docutils literal notranslate"><span class="pre">write()</span></code> have been sent to the client.</p>
|
||
</section>
|
||
</section>
|
||
<section id="unicode-issues">
|
||
<h3><a class="toc-backref" href="#unicode-issues" role="doc-backlink">Unicode Issues</a></h3>
|
||
<p>HTTP does not directly support Unicode, and neither does this
|
||
interface. All encoding/decoding must be handled by the application;
|
||
all strings passed to or from the server must be standard Python byte
|
||
strings, not Unicode objects. The result of using a Unicode object
|
||
where a string object is required, is undefined.</p>
|
||
<p>Note also that strings passed to <code class="docutils literal notranslate"><span class="pre">start_response()</span></code> as a status or
|
||
as response headers <strong>must</strong> follow <span class="target" id="index-4"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a> with respect to encoding.
|
||
That is, they must either be ISO-8859-1 characters, or use <span class="target" id="index-5"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2047.html"><strong>RFC 2047</strong></a>
|
||
MIME encoding.</p>
|
||
<p>On Python platforms where the <code class="docutils literal notranslate"><span class="pre">str</span></code> or <code class="docutils literal notranslate"><span class="pre">StringType</span></code> type is in
|
||
fact Unicode-based (e.g. Jython, IronPython, Python 3000, etc.), all
|
||
“strings” referred to in this specification must contain only
|
||
code points representable in ISO-8859-1 encoding (<code class="docutils literal notranslate"><span class="pre">\u0000</span></code> through
|
||
<code class="docutils literal notranslate"><span class="pre">\u00FF</span></code>, inclusive). It is a fatal error for an application to
|
||
supply strings containing any other Unicode character or code point.
|
||
Similarly, servers and gateways <strong>must not</strong> supply
|
||
strings to an application containing any other Unicode characters.</p>
|
||
<p>Again, all strings referred to in this specification <strong>must</strong> be
|
||
of type <code class="docutils literal notranslate"><span class="pre">str</span></code> or <code class="docutils literal notranslate"><span class="pre">StringType</span></code>, and <strong>must not</strong> be of type
|
||
<code class="docutils literal notranslate"><span class="pre">unicode</span></code> or <code class="docutils literal notranslate"><span class="pre">UnicodeType</span></code>. And, even if a given platform allows
|
||
for more than 8 bits per character in <code class="docutils literal notranslate"><span class="pre">str</span></code>/<code class="docutils literal notranslate"><span class="pre">StringType</span></code> objects,
|
||
only the lower 8 bits may be used, for any value referred to in
|
||
this specification as a “string”.</p>
|
||
</section>
|
||
<section id="error-handling">
|
||
<h3><a class="toc-backref" href="#error-handling" role="doc-backlink">Error Handling</a></h3>
|
||
<p>In general, applications <strong>should</strong> try to trap their own, internal
|
||
errors, and display a helpful message in the browser. (It is up
|
||
to the application to decide what “helpful” means in this context.)</p>
|
||
<p>However, to display such a message, the application must not have
|
||
actually sent any data to the browser yet, or else it risks corrupting
|
||
the response. WSGI therefore provides a mechanism to either allow the
|
||
application to send its error message, or be automatically aborted:
|
||
the <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> argument to <code class="docutils literal notranslate"><span class="pre">start_response</span></code>. Here is an example
|
||
of its use:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
|
||
<span class="c1"># regular application code here</span>
|
||
<span class="n">status</span> <span class="o">=</span> <span class="s2">"200 Froody"</span>
|
||
<span class="n">response_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"content-type"</span><span class="p">,</span> <span class="s2">"text/plain"</span><span class="p">)]</span>
|
||
<span class="n">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="p">[</span><span class="s2">"normal body goes here"</span><span class="p">]</span>
|
||
<span class="k">except</span><span class="p">:</span>
|
||
<span class="c1"># XXX should trap runtime issues like MemoryError, KeyboardInterrupt</span>
|
||
<span class="c1"># in a separate handler before this bare 'except:'...</span>
|
||
<span class="n">status</span> <span class="o">=</span> <span class="s2">"500 Oops"</span>
|
||
<span class="n">response_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"content-type"</span><span class="p">,</span> <span class="s2">"text/plain"</span><span class="p">)]</span>
|
||
<span class="n">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">response_headers</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">())</span>
|
||
<span class="k">return</span> <span class="p">[</span><span class="s2">"error body goes here"</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If no output has been written when an exception occurs, the call to
|
||
<code class="docutils literal notranslate"><span class="pre">start_response</span></code> will return normally, and the application will
|
||
return an error body to be sent to the browser. However, if any output
|
||
has already been sent to the browser, <code class="docutils literal notranslate"><span class="pre">start_response</span></code> will reraise
|
||
the provided exception. This exception <strong>should not</strong> be trapped by
|
||
the application, and so the application will abort. The server or
|
||
gateway can then trap this (fatal) exception and abort the response.</p>
|
||
<p>Servers <strong>should</strong> trap and log any exception that aborts an
|
||
application or the iteration of its return value. If a partial
|
||
response has already been written to the browser when an application
|
||
error occurs, the server or gateway <strong>may</strong> attempt to add an error
|
||
message to the output, if the already-sent headers indicate a
|
||
<code class="docutils literal notranslate"><span class="pre">text/*</span></code> content type that the server knows how to modify cleanly.</p>
|
||
<p>Some middleware may wish to provide additional exception handling
|
||
services, or intercept and replace application error messages. In
|
||
such cases, middleware may choose to <strong>not</strong> re-raise the <code class="docutils literal notranslate"><span class="pre">exc_info</span></code>
|
||
supplied to <code class="docutils literal notranslate"><span class="pre">start_response</span></code>, but instead raise a middleware-specific
|
||
exception, or simply return without an exception after storing the
|
||
supplied arguments. This will then cause the application to return
|
||
its error body iterable (or invoke <code class="docutils literal notranslate"><span class="pre">write()</span></code>), allowing the middleware
|
||
to capture and modify the error output. These techniques will work as
|
||
long as application authors:</p>
|
||
<ol class="arabic simple">
|
||
<li>Always provide <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> when beginning an error response</li>
|
||
<li>Never trap errors raised by <code class="docutils literal notranslate"><span class="pre">start_response</span></code> when <code class="docutils literal notranslate"><span class="pre">exc_info</span></code> is
|
||
being provided</li>
|
||
</ol>
|
||
</section>
|
||
<section id="http-1-1-expect-continue">
|
||
<h3><a class="toc-backref" href="#http-1-1-expect-continue" role="doc-backlink">HTTP 1.1 Expect/Continue</a></h3>
|
||
<p>Servers and gateways that implement HTTP 1.1 <strong>must</strong> provide
|
||
transparent support for HTTP 1.1’s “expect/continue” mechanism. This
|
||
may be done in any of several ways:</p>
|
||
<ol class="arabic simple">
|
||
<li>Respond to requests containing an <code class="docutils literal notranslate"><span class="pre">Expect:</span> <span class="pre">100-continue</span></code> request
|
||
with an immediate “100 Continue” response, and proceed normally.</li>
|
||
<li>Proceed with the request normally, but provide the application
|
||
with a <code class="docutils literal notranslate"><span class="pre">wsgi.input</span></code> stream that will send the “100 Continue”
|
||
response if/when the application first attempts to read from the
|
||
input stream. The read request must then remain blocked until the
|
||
client responds.</li>
|
||
<li>Wait until the client decides that the server does not support
|
||
expect/continue, and sends the request body on its own. (This
|
||
is suboptimal, and is not recommended.)</li>
|
||
</ol>
|
||
<p>Note that these behavior restrictions do not apply for HTTP 1.0
|
||
requests, or for requests that are not directed to an application
|
||
object. For more information on HTTP 1.1 Expect/Continue, see
|
||
<span class="target" id="index-6"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a>, sections 8.2.3 and 10.1.1.</p>
|
||
</section>
|
||
<section id="other-http-features">
|
||
<h3><a class="toc-backref" href="#other-http-features" role="doc-backlink">Other HTTP Features</a></h3>
|
||
<p>In general, servers and gateways should “play dumb” and allow the
|
||
application complete control over its output. They should only make
|
||
changes that do not alter the effective semantics of the application’s
|
||
response. It is always possible for the application developer to add
|
||
middleware components to supply additional features, so server/gateway
|
||
developers should be conservative in their implementation. In a sense,
|
||
a server should consider itself to be like an HTTP “gateway server”,
|
||
with the application being an HTTP “origin server”. (See <span class="target" id="index-7"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a>,
|
||
section 1.3, for the definition of these terms.)</p>
|
||
<p>However, because WSGI servers and applications do not communicate via
|
||
HTTP, what <span class="target" id="index-8"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a> calls “hop-by-hop” headers do not apply to WSGI
|
||
internal communications. WSGI applications <strong>must not</strong> generate any
|
||
<span class="target" id="index-9"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html#section-13.5.1"><strong>“hop-by-hop” headers</strong></a>,
|
||
attempt to use HTTP features that would
|
||
require them to generate such headers, or rely on the content of
|
||
any incoming “hop-by-hop” headers in the <code class="docutils literal notranslate"><span class="pre">environ</span></code> dictionary.
|
||
WSGI servers <strong>must</strong> handle any supported inbound “hop-by-hop” headers
|
||
on their own, such as by decoding any inbound <code class="docutils literal notranslate"><span class="pre">Transfer-Encoding</span></code>,
|
||
including chunked encoding if applicable.</p>
|
||
<p>Applying these principles to a variety of HTTP features, it should be
|
||
clear that a server <strong>may</strong> handle cache validation via the
|
||
<code class="docutils literal notranslate"><span class="pre">If-None-Match</span></code> and <code class="docutils literal notranslate"><span class="pre">If-Modified-Since</span></code> request headers and the
|
||
<code class="docutils literal notranslate"><span class="pre">Last-Modified</span></code> and <code class="docutils literal notranslate"><span class="pre">ETag</span></code> response headers. However, it is
|
||
not required to do this, and the application <strong>should</strong> perform its
|
||
own cache validation if it wants to support that feature, since
|
||
the server/gateway is not required to do such validation.</p>
|
||
<p>Similarly, a server <strong>may</strong> re-encode or transport-encode an
|
||
application’s response, but the application <strong>should</strong> use a
|
||
suitable content encoding on its own, and <strong>must not</strong> apply a
|
||
transport encoding. A server <strong>may</strong> transmit byte ranges of the
|
||
application’s response if requested by the client, and the
|
||
application doesn’t natively support byte ranges. Again, however,
|
||
the application <strong>should</strong> perform this function on its own if desired.</p>
|
||
<p>Note that these restrictions on applications do not necessarily mean
|
||
that every application must reimplement every HTTP feature; many HTTP
|
||
features can be partially or fully implemented by middleware
|
||
components, thus freeing both server and application authors from
|
||
implementing the same features over and over again.</p>
|
||
</section>
|
||
<section id="thread-support">
|
||
<h3><a class="toc-backref" href="#thread-support" role="doc-backlink">Thread Support</a></h3>
|
||
<p>Thread support, or lack thereof, is also server-dependent.
|
||
Servers that can run multiple requests in parallel, <strong>should</strong> also
|
||
provide the option of running an application in a single-threaded
|
||
fashion, so that applications or frameworks that are not thread-safe
|
||
may still be used with that server.</p>
|
||
</section>
|
||
</section>
|
||
<section id="implementation-application-notes">
|
||
<h2><a class="toc-backref" href="#implementation-application-notes" role="doc-backlink">Implementation/Application Notes</a></h2>
|
||
<section id="server-extension-apis">
|
||
<h3><a class="toc-backref" href="#server-extension-apis" role="doc-backlink">Server Extension APIs</a></h3>
|
||
<p>Some server authors may wish to expose more advanced APIs, that
|
||
application or framework authors can use for specialized purposes.
|
||
For example, a gateway based on <code class="docutils literal notranslate"><span class="pre">mod_python</span></code> might wish to expose
|
||
part of the Apache API as a WSGI extension.</p>
|
||
<p>In the simplest case, this requires nothing more than defining an
|
||
<code class="docutils literal notranslate"><span class="pre">environ</span></code> variable, such as <code class="docutils literal notranslate"><span class="pre">mod_python.some_api</span></code>. But, in many
|
||
cases, the possible presence of middleware can make this difficult.
|
||
For example, an API that offers access to the same HTTP headers that
|
||
are found in <code class="docutils literal notranslate"><span class="pre">environ</span></code> variables, might return different data if
|
||
<code class="docutils literal notranslate"><span class="pre">environ</span></code> has been modified by middleware.</p>
|
||
<p>In general, any extension API that duplicates, supplants, or bypasses
|
||
some portion of WSGI functionality runs the risk of being incompatible
|
||
with middleware components. Server/gateway developers should <em>not</em>
|
||
assume that nobody will use middleware, because some framework
|
||
developers specifically intend to organize or reorganize their
|
||
frameworks to function almost entirely as middleware of various kinds.</p>
|
||
<p>So, to provide maximum compatibility, servers and gateways that
|
||
provide extension APIs that replace some WSGI functionality, <strong>must</strong>
|
||
design those APIs so that they are invoked using the portion of the
|
||
API that they replace. For example, an extension API to access HTTP
|
||
request headers must require the application to pass in its current
|
||
<code class="docutils literal notranslate"><span class="pre">environ</span></code>, so that the server/gateway may verify that HTTP headers
|
||
accessible via the API have not been altered by middleware. If the
|
||
extension API cannot guarantee that it will always agree with
|
||
<code class="docutils literal notranslate"><span class="pre">environ</span></code> about the contents of HTTP headers, it must refuse service
|
||
to the application, e.g. by raising an error, returning <code class="docutils literal notranslate"><span class="pre">None</span></code>
|
||
instead of a header collection, or whatever is appropriate to the API.</p>
|
||
<p>Similarly, if an extension API provides an alternate means of writing
|
||
response data or headers, it should require the <code class="docutils literal notranslate"><span class="pre">start_response</span></code>
|
||
callable to be passed in, before the application can obtain the
|
||
extended service. If the object passed in is not the same one that
|
||
the server/gateway originally supplied to the application, it cannot
|
||
guarantee correct operation and must refuse to provide the extended
|
||
service to the application.</p>
|
||
<p>These guidelines also apply to middleware that adds information such
|
||
as parsed cookies, form variables, sessions, and the like to
|
||
<code class="docutils literal notranslate"><span class="pre">environ</span></code>. Specifically, such middleware should provide these
|
||
features as functions which operate on <code class="docutils literal notranslate"><span class="pre">environ</span></code>, rather than simply
|
||
stuffing values into <code class="docutils literal notranslate"><span class="pre">environ</span></code>. This helps ensure that information
|
||
is calculated from <code class="docutils literal notranslate"><span class="pre">environ</span></code> <em>after</em> any middleware has done any URL
|
||
rewrites or other <code class="docutils literal notranslate"><span class="pre">environ</span></code> modifications.</p>
|
||
<p>It is very important that these “safe extension” rules be followed by
|
||
both server/gateway and middleware developers, in order to avoid a
|
||
future in which middleware developers are forced to delete any and all
|
||
extension APIs from <code class="docutils literal notranslate"><span class="pre">environ</span></code> to ensure that their mediation isn’t
|
||
being bypassed by applications using those extensions!</p>
|
||
</section>
|
||
<section id="application-configuration">
|
||
<h3><a class="toc-backref" href="#application-configuration" role="doc-backlink">Application Configuration</a></h3>
|
||
<p>This specification does not define how a server selects or obtains an
|
||
application to invoke. These and other configuration options are
|
||
highly server-specific matters. It is expected that server/gateway
|
||
authors will document how to configure the server to execute a
|
||
particular application object, and with what options (such as
|
||
threading options).</p>
|
||
<p>Framework authors, on the other hand, should document how to create an
|
||
application object that wraps their framework’s functionality. The
|
||
user, who has chosen both the server and the application framework,
|
||
must connect the two together. However, since both the framework and
|
||
the server now have a common interface, this should be merely a
|
||
mechanical matter, rather than a significant engineering effort for
|
||
each new server/framework pair.</p>
|
||
<p>Finally, some applications, frameworks, and middleware may wish to
|
||
use the <code class="docutils literal notranslate"><span class="pre">environ</span></code> dictionary to receive simple string configuration
|
||
options. Servers and gateways <strong>should</strong> support this by allowing
|
||
an application’s deployer to specify name-value pairs to be placed in
|
||
<code class="docutils literal notranslate"><span class="pre">environ</span></code>. In the simplest case, this support can consist merely of
|
||
copying all operating system-supplied environment variables from
|
||
<code class="docutils literal notranslate"><span class="pre">os.environ</span></code> into the <code class="docutils literal notranslate"><span class="pre">environ</span></code> dictionary, since the deployer in
|
||
principle can configure these externally to the server, or in the
|
||
CGI case they may be able to be set via the server’s configuration
|
||
files.</p>
|
||
<p>Applications <strong>should</strong> try to keep such required variables to a
|
||
minimum, since not all servers will support easy configuration of
|
||
them. Of course, even in the worst case, persons deploying an
|
||
application can create a script to supply the necessary configuration
|
||
values:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">the_app</span> <span class="kn">import</span> <span class="n">application</span>
|
||
|
||
<span class="k">def</span> <span class="nf">new_app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
|
||
<span class="n">environ</span><span class="p">[</span><span class="s1">'the_app.configval1'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'something'</span>
|
||
<span class="k">return</span> <span class="n">application</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>But, most existing applications and frameworks will probably only need
|
||
a single configuration value from <code class="docutils literal notranslate"><span class="pre">environ</span></code>, to indicate the location
|
||
of their application or framework-specific configuration file(s). (Of
|
||
course, applications should cache such configuration, to avoid having
|
||
to re-read it upon each invocation.)</p>
|
||
</section>
|
||
<section id="url-reconstruction">
|
||
<h3><a class="toc-backref" href="#url-reconstruction" role="doc-backlink">URL Reconstruction</a></h3>
|
||
<p>If an application wishes to reconstruct a request’s complete URL, it
|
||
may do so using the following algorithm, contributed by Ian Bicking:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">urllib</span> <span class="kn">import</span> <span class="n">quote</span>
|
||
<span class="n">url</span> <span class="o">=</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.url_scheme'</span><span class="p">]</span><span class="o">+</span><span class="s1">'://'</span>
|
||
|
||
<span class="k">if</span> <span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'HTTP_HOST'</span><span class="p">):</span>
|
||
<span class="n">url</span> <span class="o">+=</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'HTTP_HOST'</span><span class="p">]</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">url</span> <span class="o">+=</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'SERVER_NAME'</span><span class="p">]</span>
|
||
|
||
<span class="k">if</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.url_scheme'</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'https'</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'SERVER_PORT'</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'443'</span><span class="p">:</span>
|
||
<span class="n">url</span> <span class="o">+=</span> <span class="s1">':'</span> <span class="o">+</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'SERVER_PORT'</span><span class="p">]</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'SERVER_PORT'</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'80'</span><span class="p">:</span>
|
||
<span class="n">url</span> <span class="o">+=</span> <span class="s1">':'</span> <span class="o">+</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'SERVER_PORT'</span><span class="p">]</span>
|
||
|
||
<span class="n">url</span> <span class="o">+=</span> <span class="n">quote</span><span class="p">(</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'SCRIPT_NAME'</span><span class="p">,</span> <span class="s1">''</span><span class="p">))</span>
|
||
<span class="n">url</span> <span class="o">+=</span> <span class="n">quote</span><span class="p">(</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'PATH_INFO'</span><span class="p">,</span> <span class="s1">''</span><span class="p">))</span>
|
||
<span class="k">if</span> <span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'QUERY_STRING'</span><span class="p">):</span>
|
||
<span class="n">url</span> <span class="o">+=</span> <span class="s1">'?'</span> <span class="o">+</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'QUERY_STRING'</span><span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Note that such a reconstructed URL may not be precisely the same URI
|
||
as requested by the client. Server rewrite rules, for example, may
|
||
have modified the client’s originally requested URL to place it in a
|
||
canonical form.</p>
|
||
</section>
|
||
<section id="supporting-older-2-2-versions-of-python">
|
||
<h3><a class="toc-backref" href="#supporting-older-2-2-versions-of-python" role="doc-backlink">Supporting Older (<2.2) Versions of Python</a></h3>
|
||
<p>Some servers, gateways, or applications may wish to support older
|
||
(<2.2) versions of Python. This is especially important if Jython
|
||
is a target platform, since as of this writing a production-ready
|
||
version of Jython 2.2 is not yet available.</p>
|
||
<p>For servers and gateways, this is relatively straightforward:
|
||
servers and gateways targeting pre-2.2 versions of Python must
|
||
simply restrict themselves to using only a standard “for” loop to
|
||
iterate over any iterable returned by an application. This is the
|
||
only way to ensure source-level compatibility with both the pre-2.2
|
||
iterator protocol (discussed further below) and “today’s” iterator
|
||
protocol (see <a class="pep reference internal" href="../pep-0234/" title="PEP 234 – Iterators">PEP 234</a>).</p>
|
||
<p>(Note that this technique necessarily applies only to servers,
|
||
gateways, or middleware that are written in Python. Discussion of
|
||
how to use iterator protocol(s) correctly from other languages is
|
||
outside the scope of this PEP.)</p>
|
||
<p>For applications, supporting pre-2.2 versions of Python is slightly
|
||
more complex:</p>
|
||
<ul class="simple">
|
||
<li>You may not return a file object and expect it to work as an iterable,
|
||
since before Python 2.2, files were not iterable. (In general, you
|
||
shouldn’t do this anyway, because it will perform quite poorly most
|
||
of the time!) Use <code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code> or an application-specific
|
||
file wrapper class. (See <a class="reference internal" href="#optional-platform-specific-file-handling">Optional Platform-Specific File Handling</a>
|
||
for more on <code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code>, and an example class you can use
|
||
to wrap a file as an iterable.)</li>
|
||
<li>If you return a custom iterable, it <strong>must</strong> implement the pre-2.2
|
||
iterator protocol. That is, provide a <code class="docutils literal notranslate"><span class="pre">__getitem__</span></code> method that
|
||
accepts an integer key, and raises <code class="docutils literal notranslate"><span class="pre">IndexError</span></code> when exhausted.
|
||
(Note that built-in sequence types are also acceptable, since they
|
||
also implement this protocol.)</li>
|
||
</ul>
|
||
<p>Finally, middleware that wishes to support pre-2.2 versions of Python,
|
||
and iterates over application return values or itself returns an
|
||
iterable (or both), must follow the appropriate recommendations above.</p>
|
||
<p>(Note: It should go without saying that to support pre-2.2 versions
|
||
of Python, any server, gateway, application, or middleware must also
|
||
use only language features available in the target version, use
|
||
1 and 0 instead of <code class="docutils literal notranslate"><span class="pre">True</span></code> and <code class="docutils literal notranslate"><span class="pre">False</span></code>, etc.)</p>
|
||
</section>
|
||
<section id="optional-platform-specific-file-handling">
|
||
<h3><a class="toc-backref" href="#optional-platform-specific-file-handling" role="doc-backlink">Optional Platform-Specific File Handling</a></h3>
|
||
<p>Some operating environments provide special high-performance
|
||
file-transmission facilities, such as the Unix <code class="docutils literal notranslate"><span class="pre">sendfile()</span></code> call.
|
||
Servers and gateways <strong>may</strong> expose this functionality via an optional
|
||
<code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code> key in the <code class="docutils literal notranslate"><span class="pre">environ</span></code>. An application
|
||
<strong>may</strong> use this “file wrapper” to convert a file or file-like object
|
||
into an iterable that it then returns, e.g.:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="s1">'wsgi.file_wrapper'</span> <span class="ow">in</span> <span class="n">environ</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.file_wrapper'</span><span class="p">](</span><span class="n">filelike</span><span class="p">,</span> <span class="n">block_size</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">filelike</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">block_size</span><span class="p">),</span> <span class="s1">''</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>If the server or gateway supplies <code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code>, it must be
|
||
a callable that accepts one required positional parameter, and one
|
||
optional positional parameter. The first parameter is the file-like
|
||
object to be sent, and the second parameter is an optional block
|
||
size “suggestion” (which the server/gateway need not use). The
|
||
callable <strong>must</strong> return an iterable object, and <strong>must not</strong> perform
|
||
any data transmission until and unless the server/gateway actually
|
||
receives the iterable as a return value from the application.
|
||
(To do otherwise would prevent middleware from being able to interpret
|
||
or override the response data.)</p>
|
||
<p>To be considered “file-like”, the object supplied by the application
|
||
must have a <code class="docutils literal notranslate"><span class="pre">read()</span></code> method that takes an optional size argument.
|
||
It <strong>may</strong> have a <code class="docutils literal notranslate"><span class="pre">close()</span></code> method, and if so, the iterable returned
|
||
by <code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code> <strong>must</strong> have a <code class="docutils literal notranslate"><span class="pre">close()</span></code> method that
|
||
invokes the original file-like object’s <code class="docutils literal notranslate"><span class="pre">close()</span></code> method. If the
|
||
“file-like” object has any other methods or attributes with names
|
||
matching those of Python built-in file objects (e.g. <code class="docutils literal notranslate"><span class="pre">fileno()</span></code>),
|
||
the <code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code> <strong>may</strong> assume that these methods or
|
||
attributes have the same semantics as those of a built-in file object.</p>
|
||
<p>The actual implementation of any platform-specific file handling
|
||
must occur <strong>after</strong> the application returns, and the server or
|
||
gateway checks to see if a wrapper object was returned. (Again,
|
||
because of the presence of middleware, error handlers, and the like,
|
||
it is not guaranteed that any wrapper created will actually be used.)</p>
|
||
<p>Apart from the handling of <code class="docutils literal notranslate"><span class="pre">close()</span></code>, the semantics of returning a
|
||
file wrapper from the application should be the same as if the
|
||
application had returned <code class="docutils literal notranslate"><span class="pre">iter(filelike.read,</span> <span class="pre">'')</span></code>. In other words,
|
||
transmission should begin at the current position within the “file”
|
||
at the time that transmission begins, and continue until the end is
|
||
reached.</p>
|
||
<p>Of course, platform-specific file transmission APIs don’t usually
|
||
accept arbitrary “file-like” objects. Therefore, a
|
||
<code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code> has to introspect the supplied object for
|
||
things such as a <code class="docutils literal notranslate"><span class="pre">fileno()</span></code> (Unix-like OSes) or a
|
||
<code class="docutils literal notranslate"><span class="pre">java.nio.FileChannel</span></code> (under Jython) in order to determine if
|
||
the file-like object is suitable for use with the platform-specific
|
||
API it supports.</p>
|
||
<p>Note that even if the object is <em>not</em> suitable for the platform API,
|
||
the <code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code> <strong>must</strong> still return an iterable that wraps
|
||
<code class="docutils literal notranslate"><span class="pre">read()</span></code> and <code class="docutils literal notranslate"><span class="pre">close()</span></code>, so that applications using file wrappers
|
||
are portable across platforms. Here’s a simple platform-agnostic
|
||
file wrapper class, suitable for old (pre 2.2) and new Pythons alike:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">FileWrapper</span><span class="p">:</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filelike</span><span class="p">,</span> <span class="n">blksize</span><span class="o">=</span><span class="mi">8192</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">filelike</span> <span class="o">=</span> <span class="n">filelike</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">blksize</span> <span class="o">=</span> <span class="n">blksize</span>
|
||
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">filelike</span><span class="p">,</span> <span class="s1">'close'</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">close</span> <span class="o">=</span> <span class="n">filelike</span><span class="o">.</span><span class="n">close</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
|
||
<span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">filelike</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">blksize</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">data</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">data</span>
|
||
<span class="k">raise</span> <span class="ne">IndexError</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>and here is a snippet from a server/gateway that uses it to provide
|
||
access to a platform-specific API:</p>
|
||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">environ</span><span class="p">[</span><span class="s1">'wsgi.file_wrapper'</span><span class="p">]</span> <span class="o">=</span> <span class="n">FileWrapper</span>
|
||
<span class="n">result</span> <span class="o">=</span> <span class="n">application</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
|
||
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">FileWrapper</span><span class="p">):</span>
|
||
<span class="c1"># check if result.filelike is usable w/platform-specific</span>
|
||
<span class="c1"># API, and if so, use that API to transmit the result.</span>
|
||
<span class="c1"># If not, fall through to normal iterable handling</span>
|
||
<span class="c1"># loop below.</span>
|
||
|
||
<span class="k">for</span> <span class="n">data</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
|
||
<span class="c1"># etc.</span>
|
||
|
||
<span class="k">finally</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="s1">'close'</span><span class="p">):</span>
|
||
<span class="n">result</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="questions-and-answers">
|
||
<h2><a class="toc-backref" href="#questions-and-answers" role="doc-backlink">Questions and Answers</a></h2>
|
||
<ol class="arabic">
|
||
<li>Why must <code class="docutils literal notranslate"><span class="pre">environ</span></code> be a dictionary? What’s wrong with using a
|
||
subclass?<p>The rationale for requiring a dictionary is to maximize portability
|
||
between servers. The alternative would be to define some subset of
|
||
a dictionary’s methods as being the standard and portable
|
||
interface. In practice, however, most servers will probably find a
|
||
dictionary adequate to their needs, and thus framework authors will
|
||
come to expect the full set of dictionary features to be available,
|
||
since they will be there more often than not. But, if some server
|
||
chooses <em>not</em> to use a dictionary, then there will be
|
||
interoperability problems despite that server’s “conformance” to
|
||
spec. Therefore, making a dictionary mandatory simplifies the
|
||
specification and guarantees interoperability.</p>
|
||
<p>Note that this does not prevent server or framework developers from
|
||
offering specialized services as custom variables <em>inside</em> the
|
||
<code class="docutils literal notranslate"><span class="pre">environ</span></code> dictionary. This is the recommended approach for
|
||
offering any such value-added services.</p>
|
||
</li>
|
||
<li>Why can you call <code class="docutils literal notranslate"><span class="pre">write()</span></code> <em>and</em> yield strings/return an
|
||
iterable? Shouldn’t we pick just one way?<p>If we supported only the iteration approach, then current
|
||
frameworks that assume the availability of “push” suffer. But, if
|
||
we only support pushing via <code class="docutils literal notranslate"><span class="pre">write()</span></code>, then server performance
|
||
suffers for transmission of e.g. large files (if a worker thread
|
||
can’t begin work on a new request until all of the output has been
|
||
sent). Thus, this compromise allows an application framework to
|
||
support both approaches, as appropriate, but with only a little
|
||
more burden to the server implementor than a push-only approach
|
||
would require.</p>
|
||
</li>
|
||
<li>What’s the <code class="docutils literal notranslate"><span class="pre">close()</span></code> for?<p>When writes are done during the execution of an application
|
||
object, the application can ensure that resources are released
|
||
using a try/finally block. But, if the application returns an
|
||
iterable, any resources used will not be released until the
|
||
iterable is garbage collected. The <code class="docutils literal notranslate"><span class="pre">close()</span></code> idiom allows an
|
||
application to release critical resources at the end of a request,
|
||
and it’s forward-compatible with the support for try/finally in
|
||
generators that’s proposed by <a class="pep reference internal" href="../pep-0325/" title="PEP 325 – Resource-Release Support for Generators">PEP 325</a>.</p>
|
||
</li>
|
||
<li>Why is this interface so low-level? I want feature X! (e.g.
|
||
cookies, sessions, persistence, …)<p>This isn’t Yet Another Python Web Framework. It’s just a way for
|
||
frameworks to talk to web servers, and vice versa. If you want
|
||
these features, you need to pick a web framework that provides the
|
||
features you want. And if that framework lets you create a WSGI
|
||
application, you should be able to run it in most WSGI-supporting
|
||
servers. Also, some WSGI servers may offer additional services via
|
||
objects provided in their <code class="docutils literal notranslate"><span class="pre">environ</span></code> dictionary; see the
|
||
applicable server documentation for details. (Of course,
|
||
applications that use such extensions will not be portable to other
|
||
WSGI-based servers.)</p>
|
||
</li>
|
||
<li>Why use CGI variables instead of good old HTTP headers? And why
|
||
mix them in with WSGI-defined variables?<p>Many existing web frameworks are built heavily upon the CGI spec,
|
||
and existing web servers know how to generate CGI variables. In
|
||
contrast, alternative ways of representing inbound HTTP information
|
||
are fragmented and lack market share. Thus, using the CGI
|
||
“standard” seems like a good way to leverage existing
|
||
implementations. As for mixing them with WSGI variables,
|
||
separating them would just require two dictionary arguments to be
|
||
passed around, while providing no real benefits.</p>
|
||
</li>
|
||
<li>What about the status string? Can’t we just use the number,
|
||
passing in <code class="docutils literal notranslate"><span class="pre">200</span></code> instead of <code class="docutils literal notranslate"><span class="pre">"200</span> <span class="pre">OK"</span></code>?<p>Doing this would complicate the server or gateway, by requiring
|
||
them to have a table of numeric statuses and corresponding
|
||
messages. By contrast, it is easy for an application or framework
|
||
author to type the extra text to go with the specific response code
|
||
they are using, and existing frameworks often already have a table
|
||
containing the needed messages. So, on balance it seems better to
|
||
make the application/framework responsible, rather than the server
|
||
or gateway.</p>
|
||
</li>
|
||
<li>Why is <code class="docutils literal notranslate"><span class="pre">wsgi.run_once</span></code> not guaranteed to run the app only once?<p>Because it’s merely a suggestion to the application that it should
|
||
“rig for infrequent running”. This is intended for application
|
||
frameworks that have multiple modes of operation for caching,
|
||
sessions, and so forth. In a “multiple run” mode, such frameworks
|
||
may preload caches, and may not write e.g. logs or session data to
|
||
disk after each request. In “single run” mode, such frameworks
|
||
avoid preloading and flush all necessary writes after each request.</p>
|
||
<p>However, in order to test an application or framework to verify
|
||
correct operation in the latter mode, it may be necessary (or at
|
||
least expedient) to invoke it more than once. Therefore, an
|
||
application should not assume that it will definitely not be run
|
||
again, just because it is called with <code class="docutils literal notranslate"><span class="pre">wsgi.run_once</span></code> set to
|
||
<code class="docutils literal notranslate"><span class="pre">True</span></code>.</p>
|
||
</li>
|
||
<li>Feature X (dictionaries, callables, etc.) are ugly for use in
|
||
application code; why don’t we use objects instead?<p>All of these implementation choices of WSGI are specifically
|
||
intended to <em>decouple</em> features from one another; recombining these
|
||
features into encapsulated objects makes it somewhat harder to
|
||
write servers or gateways, and an order of magnitude harder to
|
||
write middleware that replaces or modifies only small portions of
|
||
the overall functionality.</p>
|
||
<p>In essence, middleware wants to have a “Chain of Responsibility”
|
||
pattern, whereby it can act as a “handler” for some functions,
|
||
while allowing others to remain unchanged. This is difficult to do
|
||
with ordinary Python objects, if the interface is to remain
|
||
extensible. For example, one must use <code class="docutils literal notranslate"><span class="pre">__getattr__</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">__getattribute__</span></code> overrides, to ensure that extensions (such as
|
||
attributes defined by future WSGI versions) are passed through.</p>
|
||
<p>This type of code is notoriously difficult to get 100% correct, and
|
||
few people will want to write it themselves. They will therefore
|
||
copy other people’s implementations, but fail to update them when
|
||
the person they copied from corrects yet another corner case.</p>
|
||
<p>Further, this necessary boilerplate would be pure excise, a
|
||
developer tax paid by middleware developers to support a slightly
|
||
prettier API for application framework developers. But,
|
||
application framework developers will typically only be updating
|
||
<em>one</em> framework to support WSGI, and in a very limited part of
|
||
their framework as a whole. It will likely be their first (and
|
||
maybe their only) WSGI implementation, and thus they will likely
|
||
implement with this specification ready to hand. Thus, the effort
|
||
of making the API “prettier” with object attributes and suchlike
|
||
would likely be wasted for this audience.</p>
|
||
<p>We encourage those who want a prettier (or otherwise improved) WSGI
|
||
interface for use in direct web application programming (as opposed
|
||
to web framework development) to develop APIs or frameworks that
|
||
wrap WSGI for convenient use by application developers. In this
|
||
way, WSGI can remain conveniently low-level for server and
|
||
middleware authors, while not being “ugly” for application
|
||
developers.</p>
|
||
</li>
|
||
</ol>
|
||
</section>
|
||
<section id="proposed-under-discussion">
|
||
<h2><a class="toc-backref" href="#proposed-under-discussion" role="doc-backlink">Proposed/Under Discussion</a></h2>
|
||
<p>These items are currently being discussed on the Web-SIG and elsewhere,
|
||
or are on the PEP author’s “to-do” list:</p>
|
||
<ul class="simple">
|
||
<li>Should <code class="docutils literal notranslate"><span class="pre">wsgi.input</span></code> be an iterator instead of a file? This would
|
||
help for asynchronous applications and chunked-encoding input
|
||
streams.</li>
|
||
<li>Optional extensions are being discussed for pausing iteration of an
|
||
application’s output until input is available or until a callback
|
||
occurs.</li>
|
||
<li>Add a section about synchronous vs. asynchronous apps and servers,
|
||
the relevant threading models, and issues/design goals in these
|
||
areas.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="acknowledgements">
|
||
<h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2>
|
||
<p>Thanks go to the many folks on the Web-SIG mailing list whose
|
||
thoughtful feedback made this revised draft possible. Especially:</p>
|
||
<ul class="simple">
|
||
<li>Gregory “Grisha” Trubetskoy, author of <code class="docutils literal notranslate"><span class="pre">mod_python</span></code>, who beat up
|
||
on the first draft as not offering any advantages over “plain old
|
||
CGI”, thus encouraging me to look for a better approach.</li>
|
||
<li>Ian Bicking, who helped nag me into properly specifying the
|
||
multithreading and multiprocess options, as well as badgering me to
|
||
provide a mechanism for servers to supply custom extension data to
|
||
an application.</li>
|
||
<li>Tony Lownds, who came up with the concept of a <code class="docutils literal notranslate"><span class="pre">start_response</span></code>
|
||
function that took the status and headers, returning a <code class="docutils literal notranslate"><span class="pre">write</span></code>
|
||
function. His input also guided the design of the exception handling
|
||
facilities, especially in the area of allowing for middleware that
|
||
overrides application error messages.</li>
|
||
<li>Alan Kennedy, whose courageous attempts to implement WSGI-on-Jython
|
||
(well before the spec was finalized) helped to shape the “supporting
|
||
older versions of Python” section, as well as the optional
|
||
<code class="docutils literal notranslate"><span class="pre">wsgi.file_wrapper</span></code> facility.</li>
|
||
<li>Mark Nottingham, who reviewed the spec extensively for issues with
|
||
HTTP RFC compliance, especially with regard to HTTP/1.1 features that
|
||
I didn’t even know existed until he pointed them out.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="references">
|
||
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
|
||
<aside class="footnote-list brackets">
|
||
<aside class="footnote brackets" id="id4" role="doc-footnote">
|
||
<dt class="label" id="id4">[<a href="#id1">1</a>]</dt>
|
||
<dd>The Python Wiki “Web Programming” topic
|
||
(<a class="reference external" href="http://www.python.org/cgi-bin/moinmoin/WebProgramming">http://www.python.org/cgi-bin/moinmoin/WebProgramming</a>)</aside>
|
||
<aside class="footnote brackets" id="id5" role="doc-footnote">
|
||
<dt class="label" id="id5">[<a href="#id2">2</a>]</dt>
|
||
<dd>The Common Gateway Interface Specification, v 1.1, 3rd Draft
|
||
(<a class="reference external" href="https://datatracker.ietf.org/doc/html/draft-coar-cgi-v11-03">https://datatracker.ietf.org/doc/html/draft-coar-cgi-v11-03</a>)</aside>
|
||
<aside class="footnote brackets" id="id6" role="doc-footnote">
|
||
<dt class="label" id="id6">[<a href="#id3">3</a>]</dt>
|
||
<dd>mod_ssl Reference, “Environment Variables”
|
||
(<a class="reference external" href="http://www.modssl.org/docs/2.8/ssl_reference.html#ToC25">http://www.modssl.org/docs/2.8/ssl_reference.html#ToC25</a>)</aside>
|
||
</aside>
|
||
</section>
|
||
<section id="copyright">
|
||
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
||
<p>This document has been placed in the public domain.</p>
|
||
</section>
|
||
</section>
|
||
<hr class="docutils" />
|
||
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0333.rst">https://github.com/python/peps/blob/main/peps/pep-0333.rst</a></p>
|
||
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0333.rst">2023-09-09 17:39:29 GMT</a></p>
|
||
|
||
</article>
|
||
<nav id="pep-sidebar">
|
||
<h2>Contents</h2>
|
||
<ul>
|
||
<li><a class="reference internal" href="#preface">Preface</a></li>
|
||
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
||
<li><a class="reference internal" href="#rationale-and-goals">Rationale and Goals</a></li>
|
||
<li><a class="reference internal" href="#specification-overview">Specification Overview</a><ul>
|
||
<li><a class="reference internal" href="#the-application-framework-side">The Application/Framework Side</a></li>
|
||
<li><a class="reference internal" href="#the-server-gateway-side">The Server/Gateway Side</a></li>
|
||
<li><a class="reference internal" href="#middleware-components-that-play-both-sides">Middleware: Components that Play Both Sides</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#specification-details">Specification Details</a><ul>
|
||
<li><a class="reference internal" href="#environ-variables"><code class="docutils literal notranslate"><span class="pre">environ</span></code> Variables</a><ul>
|
||
<li><a class="reference internal" href="#input-and-error-streams">Input and Error Streams</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#the-start-response-callable">The <code class="docutils literal notranslate"><span class="pre">start_response()</span></code> Callable</a><ul>
|
||
<li><a class="reference internal" href="#handling-the-content-length-header">Handling the <code class="docutils literal notranslate"><span class="pre">Content-Length</span></code> Header</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#buffering-and-streaming">Buffering and Streaming</a><ul>
|
||
<li><a class="reference internal" href="#middleware-handling-of-block-boundaries">Middleware Handling of Block Boundaries</a></li>
|
||
<li><a class="reference internal" href="#the-write-callable">The <code class="docutils literal notranslate"><span class="pre">write()</span></code> Callable</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#unicode-issues">Unicode Issues</a></li>
|
||
<li><a class="reference internal" href="#error-handling">Error Handling</a></li>
|
||
<li><a class="reference internal" href="#http-1-1-expect-continue">HTTP 1.1 Expect/Continue</a></li>
|
||
<li><a class="reference internal" href="#other-http-features">Other HTTP Features</a></li>
|
||
<li><a class="reference internal" href="#thread-support">Thread Support</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#implementation-application-notes">Implementation/Application Notes</a><ul>
|
||
<li><a class="reference internal" href="#server-extension-apis">Server Extension APIs</a></li>
|
||
<li><a class="reference internal" href="#application-configuration">Application Configuration</a></li>
|
||
<li><a class="reference internal" href="#url-reconstruction">URL Reconstruction</a></li>
|
||
<li><a class="reference internal" href="#supporting-older-2-2-versions-of-python">Supporting Older (<2.2) Versions of Python</a></li>
|
||
<li><a class="reference internal" href="#optional-platform-specific-file-handling">Optional Platform-Specific File Handling</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#questions-and-answers">Questions and Answers</a></li>
|
||
<li><a class="reference internal" href="#proposed-under-discussion">Proposed/Under Discussion</a></li>
|
||
<li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li>
|
||
<li><a class="reference internal" href="#references">References</a></li>
|
||
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
||
</ul>
|
||
|
||
<br>
|
||
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0333.rst">Page Source (GitHub)</a>
|
||
</nav>
|
||
</section>
|
||
<script src="../_static/colour_scheme.js"></script>
|
||
<script src="../_static/wrap_tables.js"></script>
|
||
<script src="../_static/sticky_banner.js"></script>
|
||
</body>
|
||
</html> |