[pre-commit.ci lite] apply automatic fixes

This commit is contained in:
pre-commit-ci-lite[bot] 2025-04-11 03:04:22 +00:00 committed by GitHub
parent b3ae3117f9
commit 3d83d8138c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
102 changed files with 26790 additions and 26749 deletions

View file

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Apache httpd &#8212; Flask Documentation (3.2.x)</title>
<title>gevent &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
@ -15,8 +15,8 @@
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Using async and await" href="../async-await.html" />
<link rel="prev" title="nginx" href="nginx.html" />
<link rel="next" title="eventlet" href="eventlet.html" />
<link rel="prev" title="uWSGI" href="uwsgi.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,76 +28,83 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="../async-await.html" title="Using async and await"
<a href="eventlet.html" title="eventlet"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="nginx.html" title="nginx"
<a href="uwsgi.html" title="uWSGI"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Apache httpd</a></li>
<li class="nav-item nav-item-this"><a href="">gevent</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="apache-httpd">
<h1>Apache httpd<a class="headerlink" href="#apache-httpd" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://httpd.apache.org/">Apache httpd</a> is a fast, production level HTTP server. When serving
your application with one of the WSGI servers listed in <a class="reference internal" href="index.html"><span class="doc">Deploying to Production</span></a>, it
is often good or necessary to put a dedicated HTTP server in front of
it. This “reverse proxy” can handle incoming requests, TLS, and other
security and performance concerns better than the WSGI server.</p>
<p>httpd can be installed using your system package manager, or a pre-built
executable for Windows. Installing and running httpd itself is outside
the scope of this doc. This page outlines the basics of configuring
httpd to proxy your application. Be sure to read its documentation to
understand what features are available.</p>
<section id="domain-name">
<h2>Domain Name<a class="headerlink" href="#domain-name" title="Link to this heading"></a></h2>
<p>Acquiring and configuring a domain name is outside the scope of this
doc. In general, you will buy a domain name from a registrar, pay for
server space with a hosting provider, and then point your registrar
at the hosting providers name servers.</p>
<p>To simulate this, you can also edit your <code class="docutils literal notranslate"><span class="pre">hosts</span></code> file, located at
<code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code> on Linux. Add a line that associates a name with the
local IP.</p>
<p>Modern Linux systems may be configured to treat any domain name that
ends with <code class="docutils literal notranslate"><span class="pre">.localhost</span></code> like this without adding it to the <code class="docutils literal notranslate"><span class="pre">hosts</span></code>
file.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="mf">127.0.0.1</span> <span class="n">hello</span><span class="o">.</span><span class="n">localhost</span>
<section id="gevent">
<h1>gevent<a class="headerlink" href="#gevent" title="Link to this heading"></a></h1>
<p>Prefer using <a class="reference internal" href="gunicorn.html"><span class="doc">Gunicorn</span></a> or <a class="reference internal" href="uwsgi.html"><span class="doc">uWSGI</span></a> with gevent workers rather
than using <a class="reference external" href="https://www.gevent.org/">gevent</a> directly. Gunicorn and uWSGI provide much more
configurable and production-tested servers.</p>
<p><a class="reference external" href="https://www.gevent.org/">gevent</a> allows writing asynchronous, coroutine-based code that looks
like standard synchronous Python. It uses <a class="reference external" href="https://greenlet.readthedocs.io/en/latest/">greenlet</a> to enable task
switching without writing <code class="docutils literal notranslate"><span class="pre">async/await</span></code> or using <code class="docutils literal notranslate"><span class="pre">asyncio</span></code>.</p>
<p><a class="reference internal" href="eventlet.html"><span class="doc">eventlet</span></a> is another library that does the same thing. Certain
dependencies you have, or other considerations, may affect which of the
two you choose to use.</p>
<p>gevent provides a WSGI server that can handle many connections at once
instead of one per worker process. You must actually use gevent in your
own code to see any benefit to using the server.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>When using gevent, greenlet&gt;=1.0 is required, otherwise context locals
such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected. When using PyPy,
PyPy&gt;=7.3.7 is required.</p>
<p>Create a virtualenv, install your application, then install <code class="docutils literal notranslate"><span class="pre">gevent</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install gevent
</pre></div>
</div>
</div>
</section>
<section id="configuration">
<h2>Configuration<a class="headerlink" href="#configuration" title="Link to this heading"></a></h2>
<p>The httpd configuration is located at <code class="docutils literal notranslate"><span class="pre">/etc/httpd/conf/httpd.conf</span></code> on
Linux. It may be different depending on your operating system. Check the
docs and look for <code class="docutils literal notranslate"><span class="pre">httpd.conf</span></code>.</p>
<p>Remove or comment out any existing <code class="docutils literal notranslate"><span class="pre">DocumentRoot</span></code> directive. Add the
config lines below. Well assume the WSGI server is listening locally at
<code class="docutils literal notranslate"><span class="pre">http://127.0.0.1:8000</span></code>.</p>
<div class="literal-block-wrapper docutils container" id="id3">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/httpd/conf/httpd.conf</span></code></span><a class="headerlink" href="#id3" title="Link to this code"></a></div>
<div class="highlight-apache notranslate"><div class="highlight"><pre><span></span><span class="nb">LoadModule</span><span class="w"> </span>proxy_module<span class="w"> </span>modules/mod_proxy.so
<span class="nb">LoadModule</span><span class="w"> </span>proxy_http_module<span class="w"> </span>modules/mod_proxy_http.so
<span class="nb">ProxyPass</span><span class="w"> </span>/<span class="w"> </span>http://127.0.0.1:8000/
<span class="nb">RequestHeader</span><span class="w"> </span>set<span class="w"> </span>X-Forwarded-Proto<span class="w"> </span>http
<span class="nb">RequestHeader</span><span class="w"> </span>set<span class="w"> </span>X-Forwarded-Prefix<span class="w"> </span>/
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>To use gevent to serve your application, write a script that imports its
<code class="docutils literal notranslate"><span class="pre">WSGIServer</span></code>, as well as your app or app factory.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">gevent.pywsgi</span><span class="w"> </span><span class="kn">import</span> <span class="n">WSGIServer</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
<span class="n">http_server</span> <span class="o">=</span> <span class="n">WSGIServer</span><span class="p">((</span><span class="s2">&quot;127.0.0.1&quot;</span><span class="p">,</span> <span class="mi">8000</span><span class="p">),</span> <span class="n">app</span><span class="p">)</span>
<span class="n">http_server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
</pre></div>
</div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">LoadModule</span></code> lines might already exist. If so, make sure they are
uncommented instead of adding them manually.</p>
<p>Then <a class="reference internal" href="proxy_fix.html"><span class="doc">Tell Flask it is Behind a Proxy</span></a> so that your application uses the <code class="docutils literal notranslate"><span class="pre">X-Forwarded</span></code>
headers. <code class="docutils literal notranslate"><span class="pre">X-Forwarded-For</span></code> and <code class="docutils literal notranslate"><span class="pre">X-Forwarded-Host</span></code> are automatically
set by <code class="docutils literal notranslate"><span class="pre">ProxyPass</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ python wsgi.py
</pre></div>
</div>
<p>No output is shown when the server starts.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>gevent should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of gevent.</p>
<p>You can bind to all external IPs on a non-privileged port by using
<code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> in the server arguments shown in the previous section. Dont
do this when using a reverse proxy setup, otherwise it will be possible
to bypass the proxy.</p>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
</section>
@ -109,18 +116,19 @@ set by <code class="docutils literal notranslate"><span class="pre">ProxyPass</s
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Apache httpd</a><ul>
<li><a class="reference internal" href="#domain-name">Domain Name</a></li>
<li><a class="reference internal" href="#configuration">Configuration</a></li>
<li><a class="reference internal" href="#">gevent</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
</ul>
</li>
</ul>
@ -130,8 +138,8 @@ set by <code class="docutils literal notranslate"><span class="pre">ProxyPass</s
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="nginx.html" title="previous chapter">nginx</a>
<li>Next: <a href="../async-await.html" title="next chapter">Using <code class="docutils literal notranslate"><span class="pre">async</span></code> and <code class="docutils literal notranslate"><span class="pre">await</span></code></a></ul>
<li>Previous: <a href="uwsgi.html" title="previous chapter">uWSGI</a>
<li>Next: <a href="eventlet.html" title="next chapter">eventlet</a></ul>
</li>
</ul>
</li>
@ -155,4 +163,4 @@ set by <code class="docutils literal notranslate"><span class="pre">ProxyPass</s
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ASGI &#8212; Flask Documentation (3.2.x)</title>
<title>Gunicorn &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
@ -15,8 +15,8 @@
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Tell Flask it is Behind a Proxy" href="proxy_fix.html" />
<link rel="prev" title="eventlet" href="eventlet.html" />
<link rel="next" title="Waitress" href="waitress.html" />
<link rel="prev" title="Deploying to Production" href="index.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,45 +28,124 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="proxy_fix.html" title="Tell Flask it is Behind a Proxy"
<a href="waitress.html" title="Waitress"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="eventlet.html" title="eventlet"
<a href="index.html" title="Deploying to Production"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">ASGI</a></li>
<li class="nav-item nav-item-this"><a href="">Gunicorn</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="asgi">
<h1>ASGI<a class="headerlink" href="#asgi" title="Link to this heading"></a></h1>
<p>If youd like to use an ASGI server you will need to utilise WSGI to
ASGI middleware. The asgiref
<a class="reference external" href="https://github.com/django/asgiref#wsgi-to-asgi-adapter">WsgiToAsgi</a>
adapter is recommended as it integrates with the event loop used for
Flasks <a class="reference internal" href="../async-await.html#async-await"><span class="std std-ref">Using async and await</span></a> support. You can use the adapter by
wrapping the Flask app,</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">asgiref.wsgi</span><span class="w"> </span><span class="kn">import</span> <span class="n">WsgiToAsgi</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">Flask</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="o">...</span>
<span class="n">asgi_app</span> <span class="o">=</span> <span class="n">WsgiToAsgi</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<section id="gunicorn">
<h1>Gunicorn<a class="headerlink" href="#gunicorn" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://gunicorn.org/">Gunicorn</a> is a pure Python WSGI server with simple configuration and
multiple worker implementations for performance tuning.</p>
<ul class="simple">
<li><p>It tends to integrate easily with hosting platforms.</p></li>
<li><p>It does not support Windows (but does run on WSL).</p></li>
<li><p>It is easy to install as it does not require additional dependencies
or compilation.</p></li>
<li><p>It has built-in async worker support using gevent or eventlet.</p></li>
</ul>
<p>This page outlines the basics of running Gunicorn. Be sure to read its
<a class="reference external" href="https://docs.gunicorn.org/">documentation</a> and use <code class="docutils literal notranslate"><span class="pre">gunicorn</span> <span class="pre">--help</span></code> to understand what features
are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>Gunicorn is easy to install, as it does not require external
dependencies or compilation. It runs on Windows only under WSL.</p>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">gunicorn</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install gunicorn
</pre></div>
</div>
<p>and then serving the <code class="docutils literal notranslate"><span class="pre">asgi_app</span></code> with the ASGI server, e.g. using
<a class="reference external" href="https://github.com/pgjones/hypercorn">Hypercorn</a>,</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ hypercorn module:asgi_app
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The only required argument to Gunicorn tells it how to load your Flask
application. The syntax is <code class="docutils literal notranslate"><span class="pre">{module_import}:{app_variable}</span></code>.
<code class="docutils literal notranslate"><span class="pre">module_import</span></code> is the dotted import name to the module with your
application. <code class="docutils literal notranslate"><span class="pre">app_variable</span></code> is the variable with the application. It
can also be a function call (with any arguments) if youre using the
app factory pattern.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span># equivalent to &#39;from hello import app&#39;
$ gunicorn -w 4 &#39;hello:app&#39;
# equivalent to &#39;from hello import create_app; create_app()&#39;
$ gunicorn -w 4 &#39;hello:create_app()&#39;
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: sync
Booting worker with pid: x
Booting worker with pid: x
Booting worker with pid: x
Booting worker with pid: x
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">-w</span></code> option specifies the number of processes to run; a starting
value could be <code class="docutils literal notranslate"><span class="pre">CPU</span> <span class="pre">*</span> <span class="pre">2</span></code>. The default is only 1 worker, which is
probably not what you want for the default worker type.</p>
<p>Logs for each request arent shown by default, only worker info and
errors are shown. To show access logs on stdout, use the
<code class="docutils literal notranslate"><span class="pre">--access-logfile=-</span></code> option.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>Gunicorn should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of Gunicorn.</p>
<p>You can bind to all external IPs on a non-privileged port using the
<code class="docutils literal notranslate"><span class="pre">-b</span> <span class="pre">0.0.0.0</span></code> option. Dont do this when using a reverse proxy setup,
otherwise it will be possible to bypass the proxy.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ gunicorn -w 4 -b 0.0.0.0 &#39;hello:create_app()&#39;
Listening at: http://0.0.0.0:8000 (x)
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
<section id="async-with-gevent-or-eventlet">
<h2>Async with gevent or eventlet<a class="headerlink" href="#async-with-gevent-or-eventlet" title="Link to this heading"></a></h2>
<p>The default sync worker is appropriate for many use cases. If you need
asynchronous support, Gunicorn provides workers using either <a class="reference external" href="https://www.gevent.org/">gevent</a>
or <a class="reference external" href="https://eventlet.net/">eventlet</a>. This is not the same as Pythons <code class="docutils literal notranslate"><span class="pre">async/await</span></code>, or the
ASGI server spec. You must actually use gevent/eventlet in your own code
to see any benefit to using the workers.</p>
<p>When using either gevent or eventlet, greenlet&gt;=1.0 is required,
otherwise context locals such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected.
When using PyPy, PyPy&gt;=7.3.7 is required.</p>
<p>To use gevent:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ gunicorn -k gevent &#39;hello:create_app()&#39;
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: gevent
Booting worker with pid: x
</pre></div>
</div>
<p>To use eventlet:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ gunicorn -k eventlet &#39;hello:create_app()&#39;
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: eventlet
Booting worker with pid: x
</pre></div>
</div>
</section>
</section>
@ -77,20 +156,31 @@ wrapping the Flask app,</p>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Gunicorn</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
<li><a class="reference internal" href="#async-with-gevent-or-eventlet">Async with gevent or eventlet</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="eventlet.html" title="previous chapter">eventlet</a>
<li>Next: <a href="proxy_fix.html" title="next chapter">Tell Flask it is Behind a Proxy</a></ul>
<li>Previous: <a href="index.html" title="previous chapter">Deploying to Production</a>
<li>Next: <a href="waitress.html" title="next chapter">Waitress</a></ul>
</li>
</ul>
</li>
@ -114,4 +204,4 @@ wrapping the Flask app,</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>eventlet &#8212; Flask Documentation (3.2.x)</title>
<title>Deploying to Production &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
@ -15,8 +15,8 @@
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="ASGI" href="asgi.html" />
<link rel="prev" title="gevent" href="gevent.html" />
<link rel="next" title="Gunicorn" href="gunicorn.html" />
<link rel="prev" title="Security Considerations" href="../web-security.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,84 +28,90 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="asgi.html" title="ASGI"
<a href="gunicorn.html" title="Gunicorn"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="gevent.html" title="gevent"
<a href="../web-security.html" title="Security Considerations"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">eventlet</a></li>
<li class="nav-item nav-item-this"><a href="">Deploying to Production</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="eventlet">
<h1>eventlet<a class="headerlink" href="#eventlet" title="Link to this heading"></a></h1>
<p>Prefer using <a class="reference internal" href="gunicorn.html"><span class="doc">Gunicorn</span></a> with eventlet workers rather than using
<a class="reference external" href="https://eventlet.net/">eventlet</a> directly. Gunicorn provides a much more configurable and
production-tested server.</p>
<p><a class="reference external" href="https://eventlet.net/">eventlet</a> allows writing asynchronous, coroutine-based code that looks
like standard synchronous Python. It uses <a class="reference external" href="https://greenlet.readthedocs.io/en/latest/">greenlet</a> to enable task
switching without writing <code class="docutils literal notranslate"><span class="pre">async/await</span></code> or using <code class="docutils literal notranslate"><span class="pre">asyncio</span></code>.</p>
<p><a class="reference internal" href="gevent.html"><span class="doc">gevent</span></a> is another library that does the same thing. Certain
dependencies you have, or other considerations, may affect which of the
two you choose to use.</p>
<p>eventlet provides a WSGI server that can handle many connections at once
instead of one per worker process. You must actually use eventlet in
your own code to see any benefit to using the server.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>When using eventlet, greenlet&gt;=1.0 is required, otherwise context locals
such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected. When using PyPy,
PyPy&gt;=7.3.7 is required.</p>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">eventlet</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install eventlet
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>To use eventlet to serve your application, write a script that imports
its <code class="docutils literal notranslate"><span class="pre">wsgi.server</span></code>, as well as your app or app factory.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">eventlet</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">eventlet</span><span class="w"> </span><span class="kn">import</span> <span class="n">wsgi</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
<span class="n">wsgi</span><span class="o">.</span><span class="n">server</span><span class="p">(</span><span class="n">eventlet</span><span class="o">.</span><span class="n">listen</span><span class="p">((</span><span class="s2">&quot;127.0.0.1&quot;</span><span class="p">,</span> <span class="mi">8000</span><span class="p">)),</span> <span class="n">app</span><span class="p">)</span>
</pre></div>
<section id="deploying-to-production">
<h1>Deploying to Production<a class="headerlink" href="#deploying-to-production" title="Link to this heading"></a></h1>
<p>After developing your application, youll want to make it available
publicly to other users. When youre developing locally, youre probably
using the built-in development server, debugger, and reloader. These
should not be used in production. Instead, you should use a dedicated
WSGI server or hosting platform, some of which will be described here.</p>
<p>“Production” means “not development”, which applies whether youre
serving your application publicly to millions of users or privately /
locally to a single user. <strong>Do not use the development server when
deploying to production. It is intended for use only during local
development. It is not designed to be particularly secure, stable, or
efficient.</strong></p>
<section id="self-hosted-options">
<h2>Self-Hosted Options<a class="headerlink" href="#self-hosted-options" title="Link to this heading"></a></h2>
<p>Flask is a WSGI <em>application</em>. A WSGI <em>server</em> is used to run the
application, converting incoming HTTP requests to the standard WSGI
environ, and converting outgoing WSGI responses to HTTP responses.</p>
<p>The primary goal of these docs is to familiarize you with the concepts
involved in running a WSGI application using a production WSGI server
and HTTP server. There are many WSGI servers and HTTP servers, with many
configuration possibilities. The pages below discuss the most common
servers, and show the basics of running each one. The next section
discusses platforms that can manage this for you.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="gunicorn.html">Gunicorn</a></li>
<li class="toctree-l1"><a class="reference internal" href="waitress.html">Waitress</a></li>
<li class="toctree-l1"><a class="reference internal" href="mod_wsgi.html">mod_wsgi</a></li>
<li class="toctree-l1"><a class="reference internal" href="uwsgi.html">uWSGI</a></li>
<li class="toctree-l1"><a class="reference internal" href="gevent.html">gevent</a></li>
<li class="toctree-l1"><a class="reference internal" href="eventlet.html">eventlet</a></li>
<li class="toctree-l1"><a class="reference internal" href="asgi.html">ASGI</a></li>
</ul>
</div>
<p>WSGI servers have HTTP servers built-in. However, a dedicated HTTP
server may be safer, more efficient, or more capable. Putting an HTTP
server in front of the WSGI server is called a “reverse proxy.”</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="proxy_fix.html">Tell Flask it is Behind a Proxy</a></li>
<li class="toctree-l1"><a class="reference internal" href="nginx.html">nginx</a></li>
<li class="toctree-l1"><a class="reference internal" href="apache-httpd.html">Apache httpd</a></li>
</ul>
</div>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ python wsgi.py
(x) wsgi starting up on http://127.0.0.1:8000
</pre></div>
</div>
<p>This list is not exhaustive, and you should evaluate these and other
servers based on your applications needs. Different servers will have
different capabilities, configuration, and support.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>eventlet should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of eventlet.</p>
<p>You can bind to all external IPs on a non-privileged port by using
<code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> in the server arguments shown in the previous section.
Dont do this when using a reverse proxy setup, otherwise it will be
possible to bypass the proxy.</p>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
<section id="hosting-platforms">
<h2>Hosting Platforms<a class="headerlink" href="#hosting-platforms" title="Link to this heading"></a></h2>
<p>There are many services available for hosting web applications without
needing to maintain your own server, networking, domain, etc. Some
services may have a free tier up to a certain time or bandwidth. Many of
these services use one of the WSGI servers described above, or a similar
interface. The links below are for some of the most common platforms,
which have instructions for Flask, WSGI, or Python.</p>
<ul class="simple">
<li><p><a class="reference external" href="https://help.pythonanywhere.com/pages/Flask/">PythonAnywhere</a></p></li>
<li><p><a class="reference external" href="https://cloud.google.com/appengine/docs/standard/python3/building-app">Google App Engine</a></p></li>
<li><p><a class="reference external" href="https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-python-service">Google Cloud Run</a></p></li>
<li><p><a class="reference external" href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-flask.html">AWS Elastic Beanstalk</a></p></li>
<li><p><a class="reference external" href="https://docs.microsoft.com/en-us/azure/app-service/quickstart-python">Microsoft Azure</a></p></li>
</ul>
<p>This list is not exhaustive, and you should evaluate these and other
services based on your applications needs. Different services will have
different capabilities, configuration, pricing, and support.</p>
<p>Youll probably need to <a class="reference internal" href="proxy_fix.html"><span class="doc">Tell Flask it is Behind a Proxy</span></a> when using most hosting
platforms.</p>
</section>
</section>
@ -117,19 +123,20 @@ IP address in your browser.</p>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">eventlet</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
<li><a class="reference internal" href="#">Deploying to Production</a><ul>
<li><a class="reference internal" href="#self-hosted-options">Self-Hosted Options</a><ul>
</ul>
</li>
<li><a class="reference internal" href="#hosting-platforms">Hosting Platforms</a></li>
</ul>
</li>
</ul>
@ -137,11 +144,8 @@ IP address in your browser.</p>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="gevent.html" title="previous chapter">gevent</a>
<li>Next: <a href="asgi.html" title="next chapter">ASGI</a></ul>
</li>
<li>Previous: <a href="../web-security.html" title="previous chapter">Security Considerations</a>
<li>Next: <a href="gunicorn.html" title="next chapter">Gunicorn</a>
</ul>
</li>
</ul>
@ -164,4 +168,4 @@ IP address in your browser.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>gevent &#8212; Flask Documentation (3.2.x)</title>
<title>mod_wsgi &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
@ -15,8 +15,8 @@
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="eventlet" href="eventlet.html" />
<link rel="prev" title="uWSGI" href="uwsgi.html" />
<link rel="next" title="uWSGI" href="uwsgi.html" />
<link rel="prev" title="Waitress" href="waitress.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,83 +28,98 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="eventlet.html" title="eventlet"
<a href="uwsgi.html" title="uWSGI"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="uwsgi.html" title="uWSGI"
<a href="waitress.html" title="Waitress"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">gevent</a></li>
<li class="nav-item nav-item-this"><a href="">mod_wsgi</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="gevent">
<h1>gevent<a class="headerlink" href="#gevent" title="Link to this heading"></a></h1>
<p>Prefer using <a class="reference internal" href="gunicorn.html"><span class="doc">Gunicorn</span></a> or <a class="reference internal" href="uwsgi.html"><span class="doc">uWSGI</span></a> with gevent workers rather
than using <a class="reference external" href="https://www.gevent.org/">gevent</a> directly. Gunicorn and uWSGI provide much more
configurable and production-tested servers.</p>
<p><a class="reference external" href="https://www.gevent.org/">gevent</a> allows writing asynchronous, coroutine-based code that looks
like standard synchronous Python. It uses <a class="reference external" href="https://greenlet.readthedocs.io/en/latest/">greenlet</a> to enable task
switching without writing <code class="docutils literal notranslate"><span class="pre">async/await</span></code> or using <code class="docutils literal notranslate"><span class="pre">asyncio</span></code>.</p>
<p><a class="reference internal" href="eventlet.html"><span class="doc">eventlet</span></a> is another library that does the same thing. Certain
dependencies you have, or other considerations, may affect which of the
two you choose to use.</p>
<p>gevent provides a WSGI server that can handle many connections at once
instead of one per worker process. You must actually use gevent in your
own code to see any benefit to using the server.</p>
<section id="mod-wsgi">
<h1>mod_wsgi<a class="headerlink" href="#mod-wsgi" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://modwsgi.readthedocs.io/">mod_wsgi</a> is a WSGI server integrated with the <a class="reference external" href="https://httpd.apache.org/">Apache httpd</a> server.
The modern <a class="reference external" href="https://pypi.org/project/mod-wsgi/">mod_wsgi-express</a> command makes it easy to configure and
start the server without needing to write Apache httpd configuration.</p>
<ul class="simple">
<li><p>Tightly integrated with Apache httpd.</p></li>
<li><p>Supports Windows directly.</p></li>
<li><p>Requires a compiler and the Apache development headers to install.</p></li>
<li><p>Does not require a reverse proxy setup.</p></li>
</ul>
<p>This page outlines the basics of running mod_wsgi-express, not the more
complex installation and configuration with httpd. Be sure to read the
<a class="reference external" href="https://pypi.org/project/mod-wsgi/">mod_wsgi-express</a>, <a class="reference external" href="https://modwsgi.readthedocs.io/">mod_wsgi</a>, and <a class="reference external" href="https://httpd.apache.org/">Apache httpd</a> documentation to
understand what features are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>When using gevent, greenlet&gt;=1.0 is required, otherwise context locals
such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected. When using PyPy,
PyPy&gt;=7.3.7 is required.</p>
<p>Create a virtualenv, install your application, then install <code class="docutils literal notranslate"><span class="pre">gevent</span></code>.</p>
<p>Installing mod_wsgi requires a compiler and the Apache server and
development headers installed. You will get an error if they are not.
How to install them depends on the OS and package manager that you use.</p>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">mod_wsgi</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install gevent
$ pip install mod_wsgi
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>To use gevent to serve your application, write a script that imports its
<code class="docutils literal notranslate"><span class="pre">WSGIServer</span></code>, as well as your app or app factory.</p>
<p>The only argument to <code class="docutils literal notranslate"><span class="pre">mod_wsgi-express</span></code> specifies a script containing
your Flask application, which must be called <code class="docutils literal notranslate"><span class="pre">application</span></code>. You can
write a small script to import your app with this name, or to create it
if using the app factory pattern.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">gevent.pywsgi</span><span class="w"> </span><span class="kn">import</span> <span class="n">WSGIServer</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">app</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
<span class="n">http_server</span> <span class="o">=</span> <span class="n">WSGIServer</span><span class="p">((</span><span class="s2">&quot;127.0.0.1&quot;</span><span class="p">,</span> <span class="mi">8000</span><span class="p">),</span> <span class="n">app</span><span class="p">)</span>
<span class="n">http_server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">app</span>
</pre></div>
</div>
</div>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ python wsgi.py
<div class="literal-block-wrapper docutils container" id="id3">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id3" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
</pre></div>
</div>
<p>No output is shown when the server starts.</p>
</div>
<p>Now run the <code class="docutils literal notranslate"><span class="pre">mod_wsgi-express</span> <span class="pre">start-server</span></code> command.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ mod_wsgi-express start-server wsgi.py --processes 4
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">--processes</span></code> option specifies the number of worker processes to
run; a starting value could be <code class="docutils literal notranslate"><span class="pre">CPU</span> <span class="pre">*</span> <span class="pre">2</span></code>.</p>
<p>Logs for each request arent show in the terminal. If an error occurs,
its information is written to the error log file shown when starting the
server.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>gevent should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of gevent.</p>
<p>You can bind to all external IPs on a non-privileged port by using
<code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> in the server arguments shown in the previous section. Dont
do this when using a reverse proxy setup, otherwise it will be possible
to bypass the proxy.</p>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
<p>Unlike the other WSGI servers in these docs, mod_wsgi can be run as
root to bind to privileged ports like 80 and 443. However, it must be
configured to drop permissions to a different user and group for the
worker processes.</p>
<p>For example, if you created a <code class="docutils literal notranslate"><span class="pre">hello</span></code> user and group, you should
install your virtualenv and application as that user, then tell
mod_wsgi to drop to that user after starting.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ sudo /home/hello/.venv/bin/mod_wsgi-express start-server \
/home/hello/wsgi.py \
--user hello --group hello --port 80 --processes 4
</pre></div>
</div>
</section>
</section>
@ -116,16 +131,16 @@ IP address in your browser.</p>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">gevent</a><ul>
<li><a class="reference internal" href="#">mod_wsgi</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
@ -138,8 +153,8 @@ IP address in your browser.</p>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="uwsgi.html" title="previous chapter">uWSGI</a>
<li>Next: <a href="eventlet.html" title="next chapter">eventlet</a></ul>
<li>Previous: <a href="waitress.html" title="previous chapter">Waitress</a>
<li>Next: <a href="uwsgi.html" title="next chapter">uWSGI</a></ul>
</li>
</ul>
</li>
@ -163,4 +178,4 @@ IP address in your browser.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Gunicorn &#8212; Flask Documentation (3.2.x)</title>
<title>nginx &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
@ -15,8 +15,8 @@
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Waitress" href="waitress.html" />
<link rel="prev" title="Deploying to Production" href="index.html" />
<link rel="next" title="Apache httpd" href="apache-httpd.html" />
<link rel="prev" title="Tell Flask it is Behind a Proxy" href="proxy_fix.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,123 +28,80 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="waitress.html" title="Waitress"
<a href="apache-httpd.html" title="Apache httpd"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="index.html" title="Deploying to Production"
<a href="proxy_fix.html" title="Tell Flask it is Behind a Proxy"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Gunicorn</a></li>
<li class="nav-item nav-item-this"><a href="">nginx</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="gunicorn">
<h1>Gunicorn<a class="headerlink" href="#gunicorn" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://gunicorn.org/">Gunicorn</a> is a pure Python WSGI server with simple configuration and
multiple worker implementations for performance tuning.</p>
<ul class="simple">
<li><p>It tends to integrate easily with hosting platforms.</p></li>
<li><p>It does not support Windows (but does run on WSL).</p></li>
<li><p>It is easy to install as it does not require additional dependencies
or compilation.</p></li>
<li><p>It has built-in async worker support using gevent or eventlet.</p></li>
</ul>
<p>This page outlines the basics of running Gunicorn. Be sure to read its
<a class="reference external" href="https://docs.gunicorn.org/">documentation</a> and use <code class="docutils literal notranslate"><span class="pre">gunicorn</span> <span class="pre">--help</span></code> to understand what features
are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>Gunicorn is easy to install, as it does not require external
dependencies or compilation. It runs on Windows only under WSL.</p>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">gunicorn</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install gunicorn
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The only required argument to Gunicorn tells it how to load your Flask
application. The syntax is <code class="docutils literal notranslate"><span class="pre">{module_import}:{app_variable}</span></code>.
<code class="docutils literal notranslate"><span class="pre">module_import</span></code> is the dotted import name to the module with your
application. <code class="docutils literal notranslate"><span class="pre">app_variable</span></code> is the variable with the application. It
can also be a function call (with any arguments) if youre using the
app factory pattern.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span># equivalent to &#39;from hello import app&#39;
$ gunicorn -w 4 &#39;hello:app&#39;
# equivalent to &#39;from hello import create_app; create_app()&#39;
$ gunicorn -w 4 &#39;hello:create_app()&#39;
<section id="nginx">
<h1>nginx<a class="headerlink" href="#nginx" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://nginx.org/">nginx</a> is a fast, production level HTTP server. When serving your
application with one of the WSGI servers listed in <a class="reference internal" href="index.html"><span class="doc">Deploying to Production</span></a>, it is
often good or necessary to put a dedicated HTTP server in front of it.
This “reverse proxy” can handle incoming requests, TLS, and other
security and performance concerns better than the WSGI server.</p>
<p>Nginx can be installed using your system package manager, or a pre-built
executable for Windows. Installing and running Nginx itself is outside
the scope of this doc. This page outlines the basics of configuring
Nginx to proxy your application. Be sure to read its documentation to
understand what features are available.</p>
<section id="domain-name">
<h2>Domain Name<a class="headerlink" href="#domain-name" title="Link to this heading"></a></h2>
<p>Acquiring and configuring a domain name is outside the scope of this
doc. In general, you will buy a domain name from a registrar, pay for
server space with a hosting provider, and then point your registrar
at the hosting providers name servers.</p>
<p>To simulate this, you can also edit your <code class="docutils literal notranslate"><span class="pre">hosts</span></code> file, located at
<code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code> on Linux. Add a line that associates a name with the
local IP.</p>
<p>Modern Linux systems may be configured to treat any domain name that
ends with <code class="docutils literal notranslate"><span class="pre">.localhost</span></code> like this without adding it to the <code class="docutils literal notranslate"><span class="pre">hosts</span></code>
file.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="mf">127.0.0.1</span> <span class="n">hello</span><span class="o">.</span><span class="n">localhost</span>
</pre></div>
</div>
</div>
</section>
<section id="configuration">
<h2>Configuration<a class="headerlink" href="#configuration" title="Link to this heading"></a></h2>
<p>The nginx configuration is located at <code class="docutils literal notranslate"><span class="pre">/etc/nginx/nginx.conf</span></code> on
Linux. It may be different depending on your operating system. Check the
docs and look for <code class="docutils literal notranslate"><span class="pre">nginx.conf</span></code>.</p>
<p>Remove or comment out any existing <code class="docutils literal notranslate"><span class="pre">server</span></code> section. Add a <code class="docutils literal notranslate"><span class="pre">server</span></code>
section and use the <code class="docutils literal notranslate"><span class="pre">proxy_pass</span></code> directive to point to the address the
WSGI server is listening on. Well assume the WSGI server is listening
locally at <code class="docutils literal notranslate"><span class="pre">http://127.0.0.1:8000</span></code>.</p>
<div class="literal-block-wrapper docutils container" id="id3">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/nginx.conf</span></code></span><a class="headerlink" href="#id3" title="Link to this code"></a></div>
<div class="highlight-nginx notranslate"><div class="highlight"><pre><span></span><span class="k">server</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="mi">80</span><span class="p">;</span>
<span class="w"> </span><span class="kn">server_name</span><span class="w"> </span><span class="s">_</span><span class="p">;</span>
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: sync
Booting worker with pid: x
Booting worker with pid: x
Booting worker with pid: x
Booting worker with pid: x
<span class="w"> </span><span class="kn">location</span><span class="w"> </span><span class="s">/</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">proxy_pass</span><span class="w"> </span><span class="s">http://127.0.0.1:8000/</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-For</span><span class="w"> </span><span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Proto</span><span class="w"> </span><span class="nv">$scheme</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Host</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Prefix</span><span class="w"> </span><span class="s">/</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">-w</span></code> option specifies the number of processes to run; a starting
value could be <code class="docutils literal notranslate"><span class="pre">CPU</span> <span class="pre">*</span> <span class="pre">2</span></code>. The default is only 1 worker, which is
probably not what you want for the default worker type.</p>
<p>Logs for each request arent shown by default, only worker info and
errors are shown. To show access logs on stdout, use the
<code class="docutils literal notranslate"><span class="pre">--access-logfile=-</span></code> option.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>Gunicorn should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of Gunicorn.</p>
<p>You can bind to all external IPs on a non-privileged port using the
<code class="docutils literal notranslate"><span class="pre">-b</span> <span class="pre">0.0.0.0</span></code> option. Dont do this when using a reverse proxy setup,
otherwise it will be possible to bypass the proxy.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ gunicorn -w 4 -b 0.0.0.0 &#39;hello:create_app()&#39;
Listening at: http://0.0.0.0:8000 (x)
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
<section id="async-with-gevent-or-eventlet">
<h2>Async with gevent or eventlet<a class="headerlink" href="#async-with-gevent-or-eventlet" title="Link to this heading"></a></h2>
<p>The default sync worker is appropriate for many use cases. If you need
asynchronous support, Gunicorn provides workers using either <a class="reference external" href="https://www.gevent.org/">gevent</a>
or <a class="reference external" href="https://eventlet.net/">eventlet</a>. This is not the same as Pythons <code class="docutils literal notranslate"><span class="pre">async/await</span></code>, or the
ASGI server spec. You must actually use gevent/eventlet in your own code
to see any benefit to using the workers.</p>
<p>When using either gevent or eventlet, greenlet&gt;=1.0 is required,
otherwise context locals such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected.
When using PyPy, PyPy&gt;=7.3.7 is required.</p>
<p>To use gevent:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ gunicorn -k gevent &#39;hello:create_app()&#39;
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: gevent
Booting worker with pid: x
</pre></div>
</div>
<p>To use eventlet:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ gunicorn -k eventlet &#39;hello:create_app()&#39;
Starting gunicorn 20.1.0
Listening at: http://127.0.0.1:8000 (x)
Using worker: eventlet
Booting worker with pid: x
</pre></div>
</div>
<p>Then <a class="reference internal" href="proxy_fix.html"><span class="doc">Tell Flask it is Behind a Proxy</span></a> so that your application uses these headers.</p>
</section>
</section>
@ -156,20 +113,18 @@ Booting worker with pid: x
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Gunicorn</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
<li><a class="reference internal" href="#async-with-gevent-or-eventlet">Async with gevent or eventlet</a></li>
<li><a class="reference internal" href="#">nginx</a><ul>
<li><a class="reference internal" href="#domain-name">Domain Name</a></li>
<li><a class="reference internal" href="#configuration">Configuration</a></li>
</ul>
</li>
</ul>
@ -179,8 +134,8 @@ Booting worker with pid: x
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="index.html" title="previous chapter">Deploying to Production</a>
<li>Next: <a href="waitress.html" title="next chapter">Waitress</a></ul>
<li>Previous: <a href="proxy_fix.html" title="previous chapter">Tell Flask it is Behind a Proxy</a>
<li>Next: <a href="apache-httpd.html" title="next chapter">Apache httpd</a></ul>
</li>
</ul>
</li>
@ -204,4 +159,4 @@ Booting worker with pid: x
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Deploying to Production &#8212; Flask Documentation (3.2.x)</title>
<title>Tell Flask it is Behind a Proxy &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
@ -15,8 +15,8 @@
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Gunicorn" href="gunicorn.html" />
<link rel="prev" title="Security Considerations" href="../web-security.html" />
<link rel="next" title="nginx" href="nginx.html" />
<link rel="prev" title="ASGI" href="asgi.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,91 +28,49 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="gunicorn.html" title="Gunicorn"
<a href="nginx.html" title="nginx"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../web-security.html" title="Security Considerations"
<a href="asgi.html" title="ASGI"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Deploying to Production</a></li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Tell Flask it is Behind a Proxy</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="deploying-to-production">
<h1>Deploying to Production<a class="headerlink" href="#deploying-to-production" title="Link to this heading"></a></h1>
<p>After developing your application, youll want to make it available
publicly to other users. When youre developing locally, youre probably
using the built-in development server, debugger, and reloader. These
should not be used in production. Instead, you should use a dedicated
WSGI server or hosting platform, some of which will be described here.</p>
<p>“Production” means “not development”, which applies whether youre
serving your application publicly to millions of users or privately /
locally to a single user. <strong>Do not use the development server when
deploying to production. It is intended for use only during local
development. It is not designed to be particularly secure, stable, or
efficient.</strong></p>
<section id="self-hosted-options">
<h2>Self-Hosted Options<a class="headerlink" href="#self-hosted-options" title="Link to this heading"></a></h2>
<p>Flask is a WSGI <em>application</em>. A WSGI <em>server</em> is used to run the
application, converting incoming HTTP requests to the standard WSGI
environ, and converting outgoing WSGI responses to HTTP responses.</p>
<p>The primary goal of these docs is to familiarize you with the concepts
involved in running a WSGI application using a production WSGI server
and HTTP server. There are many WSGI servers and HTTP servers, with many
configuration possibilities. The pages below discuss the most common
servers, and show the basics of running each one. The next section
discusses platforms that can manage this for you.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="gunicorn.html">Gunicorn</a></li>
<li class="toctree-l1"><a class="reference internal" href="waitress.html">Waitress</a></li>
<li class="toctree-l1"><a class="reference internal" href="mod_wsgi.html">mod_wsgi</a></li>
<li class="toctree-l1"><a class="reference internal" href="uwsgi.html">uWSGI</a></li>
<li class="toctree-l1"><a class="reference internal" href="gevent.html">gevent</a></li>
<li class="toctree-l1"><a class="reference internal" href="eventlet.html">eventlet</a></li>
<li class="toctree-l1"><a class="reference internal" href="asgi.html">ASGI</a></li>
</ul>
<section id="tell-flask-it-is-behind-a-proxy">
<h1>Tell Flask it is Behind a Proxy<a class="headerlink" href="#tell-flask-it-is-behind-a-proxy" title="Link to this heading"></a></h1>
<p>When using a reverse proxy, or many Python hosting platforms, the proxy
will intercept and forward all external requests to the local WSGI
server.</p>
<p>From the WSGI server and Flask applications perspectives, requests are
now coming from the HTTP server to the local address, rather than from
the remote address to the external server address.</p>
<p>HTTP servers should set <code class="docutils literal notranslate"><span class="pre">X-Forwarded-</span></code> headers to pass on the real
values to the application. The application can then be told to trust and
use those values by wrapping it with the
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/middleware/proxy_fix/" title="(in Werkzeug v3.1.x)"><span>X-Forwarded-For Proxy Fix</span></a> middleware provided by Werkzeug.</p>
<p>This middleware should only be used if the application is actually
behind a proxy, and should be configured with the number of proxies that
are chained in front of it. Not all proxies set all the headers. Since
incoming headers can be faked, you must set how many proxies are setting
each header so the middleware knows what to trust.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.middleware.proxy_fix</span><span class="w"> </span><span class="kn">import</span> <span class="n">ProxyFix</span>
<span class="n">app</span><span class="o">.</span><span class="n">wsgi_app</span> <span class="o">=</span> <span class="n">ProxyFix</span><span class="p">(</span>
<span class="n">app</span><span class="o">.</span><span class="n">wsgi_app</span><span class="p">,</span> <span class="n">x_for</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">x_proto</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">x_host</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">x_prefix</span><span class="o">=</span><span class="mi">1</span>
<span class="p">)</span>
</pre></div>
</div>
<p>WSGI servers have HTTP servers built-in. However, a dedicated HTTP
server may be safer, more efficient, or more capable. Putting an HTTP
server in front of the WSGI server is called a “reverse proxy.”</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="proxy_fix.html">Tell Flask it is Behind a Proxy</a></li>
<li class="toctree-l1"><a class="reference internal" href="nginx.html">nginx</a></li>
<li class="toctree-l1"><a class="reference internal" href="apache-httpd.html">Apache httpd</a></li>
</ul>
</div>
<p>This list is not exhaustive, and you should evaluate these and other
servers based on your applications needs. Different servers will have
different capabilities, configuration, and support.</p>
</section>
<section id="hosting-platforms">
<h2>Hosting Platforms<a class="headerlink" href="#hosting-platforms" title="Link to this heading"></a></h2>
<p>There are many services available for hosting web applications without
needing to maintain your own server, networking, domain, etc. Some
services may have a free tier up to a certain time or bandwidth. Many of
these services use one of the WSGI servers described above, or a similar
interface. The links below are for some of the most common platforms,
which have instructions for Flask, WSGI, or Python.</p>
<ul class="simple">
<li><p><a class="reference external" href="https://help.pythonanywhere.com/pages/Flask/">PythonAnywhere</a></p></li>
<li><p><a class="reference external" href="https://cloud.google.com/appengine/docs/standard/python3/building-app">Google App Engine</a></p></li>
<li><p><a class="reference external" href="https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-python-service">Google Cloud Run</a></p></li>
<li><p><a class="reference external" href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-flask.html">AWS Elastic Beanstalk</a></p></li>
<li><p><a class="reference external" href="https://docs.microsoft.com/en-us/azure/app-service/quickstart-python">Microsoft Azure</a></p></li>
</ul>
<p>This list is not exhaustive, and you should evaluate these and other
services based on your applications needs. Different services will have
different capabilities, configuration, pricing, and support.</p>
<p>Youll probably need to <a class="reference internal" href="proxy_fix.html"><span class="doc">Tell Flask it is Behind a Proxy</span></a> when using most hosting
platforms.</p>
</section>
<p>Remember, only apply this middleware if you are behind a proxy, and set
the correct number of proxies that set each header. It can be a security
issue if you get this configuration wrong.</p>
</section>
@ -123,29 +81,21 @@ platforms.</p>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Deploying to Production</a><ul>
<li><a class="reference internal" href="#self-hosted-options">Self-Hosted Options</a><ul>
</ul>
</li>
<li><a class="reference internal" href="#hosting-platforms">Hosting Platforms</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li>Previous: <a href="../web-security.html" title="previous chapter">Security Considerations</a>
<li>Next: <a href="gunicorn.html" title="next chapter">Gunicorn</a>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="asgi.html" title="previous chapter">ASGI</a>
<li>Next: <a href="nginx.html" title="next chapter">nginx</a></ul>
</li>
</ul>
</li>
</ul>
@ -168,4 +118,4 @@ platforms.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>mod_wsgi &#8212; Flask Documentation (3.2.x)</title>
<title>uWSGI &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
@ -15,8 +15,8 @@
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="uWSGI" href="uwsgi.html" />
<link rel="prev" title="Waitress" href="waitress.html" />
<link rel="next" title="gevent" href="gevent.html" />
<link rel="prev" title="mod_wsgi" href="mod_wsgi.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,96 +28,134 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="uwsgi.html" title="uWSGI"
<a href="gevent.html" title="gevent"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="waitress.html" title="Waitress"
<a href="mod_wsgi.html" title="mod_wsgi"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">mod_wsgi</a></li>
<li class="nav-item nav-item-this"><a href="">uWSGI</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="mod-wsgi">
<h1>mod_wsgi<a class="headerlink" href="#mod-wsgi" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://modwsgi.readthedocs.io/">mod_wsgi</a> is a WSGI server integrated with the <a class="reference external" href="https://httpd.apache.org/">Apache httpd</a> server.
The modern <a class="reference external" href="https://pypi.org/project/mod-wsgi/">mod_wsgi-express</a> command makes it easy to configure and
start the server without needing to write Apache httpd configuration.</p>
<section id="uwsgi">
<h1>uWSGI<a class="headerlink" href="#uwsgi" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/">uWSGI</a> is a fast, compiled server suite with extensive configuration
and capabilities beyond a basic server.</p>
<ul class="simple">
<li><p>Tightly integrated with Apache httpd.</p></li>
<li><p>Supports Windows directly.</p></li>
<li><p>Requires a compiler and the Apache development headers to install.</p></li>
<li><p>Does not require a reverse proxy setup.</p></li>
<li><p>It can be very performant due to being a compiled program.</p></li>
<li><p>It is complex to configure beyond the basic application, and has so
many options that it can be difficult for beginners to understand.</p></li>
<li><p>It does not support Windows (but does run on WSL).</p></li>
<li><p>It requires a compiler to install in some cases.</p></li>
</ul>
<p>This page outlines the basics of running mod_wsgi-express, not the more
complex installation and configuration with httpd. Be sure to read the
<a class="reference external" href="https://pypi.org/project/mod-wsgi/">mod_wsgi-express</a>, <a class="reference external" href="https://modwsgi.readthedocs.io/">mod_wsgi</a>, and <a class="reference external" href="https://httpd.apache.org/">Apache httpd</a> documentation to
understand what features are available.</p>
<p>This page outlines the basics of running uWSGI. Be sure to read its
documentation to understand what features are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>Installing mod_wsgi requires a compiler and the Apache server and
development headers installed. You will get an error if they are not.
How to install them depends on the OS and package manager that you use.</p>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">mod_wsgi</span></code>.</p>
<p>uWSGI has multiple ways to install it. The most straightforward is to
install the <code class="docutils literal notranslate"><span class="pre">pyuwsgi</span></code> package, which provides precompiled wheels for
common platforms. However, it does not provide SSL support, which can be
provided with a reverse proxy instead.</p>
<p>Create a virtualenv, install your application, then install <code class="docutils literal notranslate"><span class="pre">pyuwsgi</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install mod_wsgi
$ pip install pyuwsgi
</pre></div>
</div>
<p>If you have a compiler available, you can install the <code class="docutils literal notranslate"><span class="pre">uwsgi</span></code> package
instead. Or install the <code class="docutils literal notranslate"><span class="pre">pyuwsgi</span></code> package from sdist instead of wheel.
Either method will include SSL support.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install uwsgi
# or
$ pip install --no-binary pyuwsgi pyuwsgi
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The only argument to <code class="docutils literal notranslate"><span class="pre">mod_wsgi-express</span></code> specifies a script containing
your Flask application, which must be called <code class="docutils literal notranslate"><span class="pre">application</span></code>. You can
write a small script to import your app with this name, or to create it
if using the app factory pattern.</p>
<p>The most basic way to run uWSGI is to tell it to start an HTTP server
and import your application.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w hello:app
*** Starting uWSGI 2.0.20 (64bit) on [x] ***
*** Operational MODE: preforking ***
mounting hello:app on /
spawned uWSGI master process (pid: x)
spawned uWSGI worker 1 (pid: x, cores: 1)
spawned uWSGI worker 2 (pid: x, cores: 1)
spawned uWSGI worker 3 (pid: x, cores: 1)
spawned uWSGI worker 4 (pid: x, cores: 1)
spawned uWSGI http 1 (pid: x)
</pre></div>
</div>
<p>If youre using the app factory pattern, youll need to create a small
Python file to create the app, then point uWSGI at that.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">app</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">app</span>
</pre></div>
</div>
</div>
<div class="literal-block-wrapper docutils container" id="id3">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id3" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
</pre></div>
</div>
</div>
<p>Now run the <code class="docutils literal notranslate"><span class="pre">mod_wsgi-express</span> <span class="pre">start-server</span></code> command.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ mod_wsgi-express start-server wsgi.py --processes 4
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w wsgi:app
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">--processes</span></code> option specifies the number of worker processes to
run; a starting value could be <code class="docutils literal notranslate"><span class="pre">CPU</span> <span class="pre">*</span> <span class="pre">2</span></code>.</p>
<p>Logs for each request arent show in the terminal. If an error occurs,
its information is written to the error log file shown when starting the
server.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">--http</span></code> option starts an HTTP server at 127.0.0.1 port 8000. The
<code class="docutils literal notranslate"><span class="pre">--master</span></code> option specifies the standard worker manager. The <code class="docutils literal notranslate"><span class="pre">-p</span></code>
option starts 4 worker processes; a starting value could be <code class="docutils literal notranslate"><span class="pre">CPU</span> <span class="pre">*</span> <span class="pre">2</span></code>.
The <code class="docutils literal notranslate"><span class="pre">-w</span></code> option tells uWSGI how to import your application</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>Unlike the other WSGI servers in these docs, mod_wsgi can be run as
root to bind to privileged ports like 80 and 443. However, it must be
configured to drop permissions to a different user and group for the
worker processes.</p>
<p>For example, if you created a <code class="docutils literal notranslate"><span class="pre">hello</span></code> user and group, you should
install your virtualenv and application as that user, then tell
mod_wsgi to drop to that user after starting.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ sudo /home/hello/.venv/bin/mod_wsgi-express start-server \
/home/hello/wsgi.py \
--user hello --group hello --port 80 --processes 4
<p>uWSGI should not be run as root with the configuration shown in this doc
because it would cause your application code to run as root, which is
not secure. However, this means it will not be possible to bind to port
80 or 443. Instead, a reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or
<a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used in front of uWSGI. It is possible to
run uWSGI as root securely, but that is beyond the scope of this doc.</p>
<p>uWSGI has optimized integration with <a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/Nginx.html">Nginx uWSGI</a> and
<a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/Apache.html#mod-proxy-uwsgi">Apache mod_proxy_uwsgi</a>, and possibly other servers, instead of using
a standard HTTP proxy. That configuration is beyond the scope of this
doc, see the links for more information.</p>
<p>You can bind to all external IPs on a non-privileged port using the
<code class="docutils literal notranslate"><span class="pre">--http</span> <span class="pre">0.0.0.0:8000</span></code> option. Dont do this when using a reverse proxy
setup, otherwise it will be possible to bypass the proxy.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 0.0.0.0:8000 --master -p 4 -w wsgi:app
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
<section id="async-with-gevent">
<h2>Async with gevent<a class="headerlink" href="#async-with-gevent" title="Link to this heading"></a></h2>
<p>The default sync worker is appropriate for many use cases. If you need
asynchronous support, uWSGI provides a <a class="reference external" href="https://www.gevent.org/">gevent</a> worker. This is not the
same as Pythons <code class="docutils literal notranslate"><span class="pre">async/await</span></code>, or the ASGI server spec. You must
actually use gevent in your own code to see any benefit to using the
worker.</p>
<p>When using gevent, greenlet&gt;=1.0 is required, otherwise context locals
such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected. When using PyPy,
PyPy&gt;=7.3.7 is required.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 127.0.0.1:8000 --master --gevent 100 -w wsgi:app
*** Starting uWSGI 2.0.20 (64bit) on [x] ***
*** Operational MODE: async ***
mounting hello:app on /
spawned uWSGI master process (pid: x)
spawned uWSGI worker 1 (pid: x, cores: 100)
spawned uWSGI http 1 (pid: x)
*** running gevent loop engine [addr:x] ***
</pre></div>
</div>
</section>
@ -131,19 +169,20 @@ mod_wsgi to drop to that user after starting.</p>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">mod_wsgi</a><ul>
<li><a class="reference internal" href="#">uWSGI</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
<li><a class="reference internal" href="#async-with-gevent">Async with gevent</a></li>
</ul>
</li>
</ul>
@ -153,8 +192,8 @@ mod_wsgi to drop to that user after starting.</p>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="waitress.html" title="previous chapter">Waitress</a>
<li>Next: <a href="uwsgi.html" title="next chapter">uWSGI</a></ul>
<li>Previous: <a href="mod_wsgi.html" title="previous chapter">mod_wsgi</a>
<li>Next: <a href="gevent.html" title="next chapter">gevent</a></ul>
</li>
</ul>
</li>
@ -178,4 +217,4 @@ mod_wsgi to drop to that user after starting.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>nginx &#8212; Flask Documentation (3.2.x)</title>
<title>Waitress &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
@ -15,8 +15,8 @@
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Apache httpd" href="apache-httpd.html" />
<link rel="prev" title="Tell Flask it is Behind a Proxy" href="proxy_fix.html" />
<link rel="next" title="mod_wsgi" href="mod_wsgi.html" />
<link rel="prev" title="Gunicorn" href="gunicorn.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,80 +28,81 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="apache-httpd.html" title="Apache httpd"
<a href="mod_wsgi.html" title="mod_wsgi"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="proxy_fix.html" title="Tell Flask it is Behind a Proxy"
<a href="gunicorn.html" title="Gunicorn"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">nginx</a></li>
<li class="nav-item nav-item-this"><a href="">Waitress</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="nginx">
<h1>nginx<a class="headerlink" href="#nginx" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://nginx.org/">nginx</a> is a fast, production level HTTP server. When serving your
application with one of the WSGI servers listed in <a class="reference internal" href="index.html"><span class="doc">Deploying to Production</span></a>, it is
often good or necessary to put a dedicated HTTP server in front of it.
This “reverse proxy” can handle incoming requests, TLS, and other
security and performance concerns better than the WSGI server.</p>
<p>Nginx can be installed using your system package manager, or a pre-built
executable for Windows. Installing and running Nginx itself is outside
the scope of this doc. This page outlines the basics of configuring
Nginx to proxy your application. Be sure to read its documentation to
understand what features are available.</p>
<section id="domain-name">
<h2>Domain Name<a class="headerlink" href="#domain-name" title="Link to this heading"></a></h2>
<p>Acquiring and configuring a domain name is outside the scope of this
doc. In general, you will buy a domain name from a registrar, pay for
server space with a hosting provider, and then point your registrar
at the hosting providers name servers.</p>
<p>To simulate this, you can also edit your <code class="docutils literal notranslate"><span class="pre">hosts</span></code> file, located at
<code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code> on Linux. Add a line that associates a name with the
local IP.</p>
<p>Modern Linux systems may be configured to treat any domain name that
ends with <code class="docutils literal notranslate"><span class="pre">.localhost</span></code> like this without adding it to the <code class="docutils literal notranslate"><span class="pre">hosts</span></code>
file.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/hosts</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="mf">127.0.0.1</span> <span class="n">hello</span><span class="o">.</span><span class="n">localhost</span>
<section id="waitress">
<h1>Waitress<a class="headerlink" href="#waitress" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://docs.pylonsproject.org/projects/waitress/">Waitress</a> is a pure Python WSGI server.</p>
<ul class="simple">
<li><p>It is easy to configure.</p></li>
<li><p>It supports Windows directly.</p></li>
<li><p>It is easy to install as it does not require additional dependencies
or compilation.</p></li>
<li><p>It does not support streaming requests, full request data is always
buffered.</p></li>
<li><p>It uses a single process with multiple thread workers.</p></li>
</ul>
<p>This page outlines the basics of running Waitress. Be sure to read its
documentation and <code class="docutils literal notranslate"><span class="pre">waitress-serve</span> <span class="pre">--help</span></code> to understand what features
are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">waitress</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install waitress
</pre></div>
</div>
</div>
</section>
<section id="configuration">
<h2>Configuration<a class="headerlink" href="#configuration" title="Link to this heading"></a></h2>
<p>The nginx configuration is located at <code class="docutils literal notranslate"><span class="pre">/etc/nginx/nginx.conf</span></code> on
Linux. It may be different depending on your operating system. Check the
docs and look for <code class="docutils literal notranslate"><span class="pre">nginx.conf</span></code>.</p>
<p>Remove or comment out any existing <code class="docutils literal notranslate"><span class="pre">server</span></code> section. Add a <code class="docutils literal notranslate"><span class="pre">server</span></code>
section and use the <code class="docutils literal notranslate"><span class="pre">proxy_pass</span></code> directive to point to the address the
WSGI server is listening on. Well assume the WSGI server is listening
locally at <code class="docutils literal notranslate"><span class="pre">http://127.0.0.1:8000</span></code>.</p>
<div class="literal-block-wrapper docutils container" id="id3">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">/etc/nginx.conf</span></code></span><a class="headerlink" href="#id3" title="Link to this code"></a></div>
<div class="highlight-nginx notranslate"><div class="highlight"><pre><span></span><span class="k">server</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="mi">80</span><span class="p">;</span>
<span class="w"> </span><span class="kn">server_name</span><span class="w"> </span><span class="s">_</span><span class="p">;</span>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The only required argument to <code class="docutils literal notranslate"><span class="pre">waitress-serve</span></code> tells it how to load
your Flask application. The syntax is <code class="docutils literal notranslate"><span class="pre">{module}:{app}</span></code>. <code class="docutils literal notranslate"><span class="pre">module</span></code> is
the dotted import name to the module with your application. <code class="docutils literal notranslate"><span class="pre">app</span></code> is
the variable with the application. If youre using the app factory
pattern, use <code class="docutils literal notranslate"><span class="pre">--call</span> <span class="pre">{module}:{factory}</span></code> instead.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span># equivalent to &#39;from hello import app&#39;
$ waitress-serve --host 127.0.0.1 hello:app
<span class="w"> </span><span class="kn">location</span><span class="w"> </span><span class="s">/</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">proxy_pass</span><span class="w"> </span><span class="s">http://127.0.0.1:8000/</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-For</span><span class="w"> </span><span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Proto</span><span class="w"> </span><span class="nv">$scheme</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Host</span><span class="w"> </span><span class="nv">$host</span><span class="p">;</span>
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">X-Forwarded-Prefix</span><span class="w"> </span><span class="s">/</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
# equivalent to &#39;from hello import create_app; create_app()&#39;
$ waitress-serve --host 127.0.0.1 --call hello:create_app
Serving on http://127.0.0.1:8080
</pre></div>
</div>
</div>
<p>Then <a class="reference internal" href="proxy_fix.html"><span class="doc">Tell Flask it is Behind a Proxy</span></a> so that your application uses these headers.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">--host</span></code> option binds the server to local <code class="docutils literal notranslate"><span class="pre">127.0.0.1</span></code> only.</p>
<p>Logs for each request arent shown, only errors are shown. Logging can
be configured through the Python interface instead of the command line.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>Waitress should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of Waitress.</p>
<p>You can bind to all external IPs on a non-privileged port by not
specifying the <code class="docutils literal notranslate"><span class="pre">--host</span></code> option. Dont do this when using a reverse
proxy setup, otherwise it will be possible to bypass the proxy.</p>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
</section>
@ -113,18 +114,19 @@ locally at <code class="docutils literal notranslate"><span class="pre">http://1
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">nginx</a><ul>
<li><a class="reference internal" href="#domain-name">Domain Name</a></li>
<li><a class="reference internal" href="#configuration">Configuration</a></li>
<li><a class="reference internal" href="#">Waitress</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
</ul>
</li>
</ul>
@ -134,8 +136,8 @@ locally at <code class="docutils literal notranslate"><span class="pre">http://1
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="proxy_fix.html" title="previous chapter">Tell Flask it is Behind a Proxy</a>
<li>Next: <a href="apache-httpd.html" title="next chapter">Apache httpd</a></ul>
<li>Previous: <a href="gunicorn.html" title="previous chapter">Gunicorn</a>
<li>Next: <a href="mod_wsgi.html" title="next chapter">mod_wsgi</a></ul>
</li>
</ul>
</li>
@ -159,4 +161,4 @@ locally at <code class="docutils literal notranslate"><span class="pre">http://1
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -1,76 +1,242 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<html lang="en" data-content_root="./">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tell Flask it is Behind a Proxy &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="nginx" href="nginx.html" />
<link rel="prev" title="ASGI" href="asgi.html" />
<title>Design Decisions in Flask &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="_static/flask.css?v=b87c8d14" />
<script src="_static/documentation_options.js?v=56528222"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Flask Extension Development" href="extensiondev.html" />
<link rel="prev" title="API" href="api.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="nginx.html" title="nginx"
<a href="extensiondev.html" title="Flask Extension Development"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="asgi.html" title="ASGI"
<a href="api.html" title="API"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Tell Flask it is Behind a Proxy</a></li>
<li class="nav-item nav-item-0"><a href="index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Design Decisions in Flask</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="tell-flask-it-is-behind-a-proxy">
<h1>Tell Flask it is Behind a Proxy<a class="headerlink" href="#tell-flask-it-is-behind-a-proxy" title="Link to this heading"></a></h1>
<p>When using a reverse proxy, or many Python hosting platforms, the proxy
will intercept and forward all external requests to the local WSGI
server.</p>
<p>From the WSGI server and Flask applications perspectives, requests are
now coming from the HTTP server to the local address, rather than from
the remote address to the external server address.</p>
<p>HTTP servers should set <code class="docutils literal notranslate"><span class="pre">X-Forwarded-</span></code> headers to pass on the real
values to the application. The application can then be told to trust and
use those values by wrapping it with the
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/middleware/proxy_fix/" title="(in Werkzeug v3.1.x)"><span>X-Forwarded-For Proxy Fix</span></a> middleware provided by Werkzeug.</p>
<p>This middleware should only be used if the application is actually
behind a proxy, and should be configured with the number of proxies that
are chained in front of it. Not all proxies set all the headers. Since
incoming headers can be faked, you must set how many proxies are setting
each header so the middleware knows what to trust.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.middleware.proxy_fix</span><span class="w"> </span><span class="kn">import</span> <span class="n">ProxyFix</span>
<span class="n">app</span><span class="o">.</span><span class="n">wsgi_app</span> <span class="o">=</span> <span class="n">ProxyFix</span><span class="p">(</span>
<span class="n">app</span><span class="o">.</span><span class="n">wsgi_app</span><span class="p">,</span> <span class="n">x_for</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">x_proto</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">x_host</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">x_prefix</span><span class="o">=</span><span class="mi">1</span>
<span class="p">)</span>
<section id="design-decisions-in-flask">
<h1>Design Decisions in Flask<a class="headerlink" href="#design-decisions-in-flask" title="Link to this heading"></a></h1>
<p>If you are curious why Flask does certain things the way it does and not
differently, this section is for you. This should give you an idea about
some of the design decisions that may appear arbitrary and surprising at
first, especially in direct comparison with other frameworks.</p>
<section id="the-explicit-application-object">
<h2>The Explicit Application Object<a class="headerlink" href="#the-explicit-application-object" title="Link to this heading"></a></h2>
<p>A Python web application based on WSGI has to have one central callable
object that implements the actual application. In Flask this is an
instance of the <a class="reference internal" href="api.html#flask.Flask" title="flask.Flask"><code class="xref py py-class docutils literal notranslate"><span class="pre">Flask</span></code></a> class. Each Flask application has
to create an instance of this class itself and pass it the name of the
module, but why cant Flask do that itself?</p>
<p>Without such an explicit application object the following code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">Flask</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="k">return</span> <span class="s1">&#39;Hello World!&#39;</span>
</pre></div>
</div>
<p>Remember, only apply this middleware if you are behind a proxy, and set
the correct number of proxies that set each header. It can be a security
issue if you get this configuration wrong.</p>
<p>Would look like this instead:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hypothetical_flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">route</span>
<span class="nd">@route</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="k">return</span> <span class="s1">&#39;Hello World!&#39;</span>
</pre></div>
</div>
<p>There are three major reasons for this. The most important one is that
implicit application objects require that there may only be one instance at
the time. There are ways to fake multiple applications with a single
application object, like maintaining a stack of applications, but this
causes some problems I wont outline here in detail. Now the question is:
when does a microframework need more than one application at the same
time? A good example for this is unit testing. When you want to test
something it can be very helpful to create a minimal application to test
specific behavior. When the application object is deleted everything it
allocated will be freed again.</p>
<p>Another thing that becomes possible when you have an explicit object lying
around in your code is that you can subclass the base class
(<a class="reference internal" href="api.html#flask.Flask" title="flask.Flask"><code class="xref py py-class docutils literal notranslate"><span class="pre">Flask</span></code></a>) to alter specific behavior. This would not be
possible without hacks if the object were created ahead of time for you
based on a class that is not exposed to you.</p>
<p>But there is another very important reason why Flask depends on an
explicit instantiation of that class: the package name. Whenever you
create a Flask instance you usually pass it <code class="code docutils literal notranslate"><span class="pre">__name__</span></code> as package name.
Flask depends on that information to properly load resources relative
to your module. With Pythons outstanding support for reflection it can
then access the package to figure out where the templates and static files
are stored (see <a class="reference internal" href="api.html#flask.Flask.open_resource" title="flask.Flask.open_resource"><code class="xref py py-meth docutils literal notranslate"><span class="pre">open_resource()</span></code></a>). Now obviously there
are frameworks around that do not need any configuration and will still be
able to load templates relative to your application module. But they have
to use the current working directory for that, which is a very unreliable
way to determine where the application is. The current working directory
is process-wide and if you are running multiple applications in one
process (which could happen in a webserver without you knowing) the paths
will be off. Worse: many webservers do not set the working directory to
the directory of your application but to the document root which does not
have to be the same folder.</p>
<p>The third reason is “explicit is better than implicit”. That object is
your WSGI application, you dont have to remember anything else. If you
want to apply a WSGI middleware, just wrap it and youre done (though
there are better ways to do that so that you do not lose the reference
to the application object <a class="reference internal" href="api.html#flask.Flask.wsgi_app" title="flask.Flask.wsgi_app"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wsgi_app()</span></code></a>).</p>
<p>Furthermore this design makes it possible to use a factory function to
create the application which is very helpful for unit testing and similar
things (<a class="reference internal" href="patterns/appfactories.html"><span class="doc">Application Factories</span></a>).</p>
</section>
<section id="the-routing-system">
<h2>The Routing System<a class="headerlink" href="#the-routing-system" title="Link to this heading"></a></h2>
<p>Flask uses the Werkzeug routing system which was designed to
automatically order routes by complexity. This means that you can declare
routes in arbitrary order and they will still work as expected. This is a
requirement if you want to properly implement decorator based routing
since decorators could be fired in undefined order when the application is
split into multiple modules.</p>
<p>Another design decision with the Werkzeug routing system is that routes
in Werkzeug try to ensure that URLs are unique. Werkzeug will go quite far
with that in that it will automatically redirect to a canonical URL if a route
is ambiguous.</p>
</section>
<section id="one-template-engine">
<h2>One Template Engine<a class="headerlink" href="#one-template-engine" title="Link to this heading"></a></h2>
<p>Flask decides on one template engine: Jinja2. Why doesnt Flask have a
pluggable template engine interface? You can obviously use a different
template engine, but Flask will still configure Jinja2 for you. While
that limitation that Jinja2 is <em>always</em> configured will probably go away,
the decision to bundle one template engine and use that will not.</p>
<p>Template engines are like programming languages and each of those engines
has a certain understanding about how things work. On the surface they
all work the same: you tell the engine to evaluate a template with a set
of variables and take the return value as string.</p>
<p>But thats about where similarities end. Jinja2 for example has an
extensive filter system, a certain way to do template inheritance,
support for reusable blocks (macros) that can be used from inside
templates and also from Python code, supports iterative template
rendering, configurable syntax and more. On the other hand an engine
like Genshi is based on XML stream evaluation, template inheritance by
taking the availability of XPath into account and more. Mako on the
other hand treats templates similar to Python modules.</p>
<p>When it comes to connecting a template engine with an application or
framework there is more than just rendering templates. For instance,
Flask uses Jinja2s extensive autoescaping support. Also it provides
ways to access macros from Jinja2 templates.</p>
<p>A template abstraction layer that would not take the unique features of
the template engines away is a science on its own and a too large
undertaking for a microframework like Flask.</p>
<p>Furthermore extensions can then easily depend on one template language
being present. You can easily use your own templating language, but an
extension could still depend on Jinja itself.</p>
</section>
<section id="what-does-micro-mean">
<h2>What does “micro” mean?<a class="headerlink" href="#what-does-micro-mean" title="Link to this heading"></a></h2>
<p>“Micro” does not mean that your whole web application has to fit into a single
Python file (although it certainly can), nor does it mean that Flask is lacking
in functionality. The “micro” in microframework means Flask aims to keep the
core simple but extensible. Flask wont make many decisions for you, such as
what database to use. Those decisions that it does make, such as what
templating engine to use, are easy to change. Everything else is up to you, so
that Flask can be everything you need and nothing you dont.</p>
<p>By default, Flask does not include a database abstraction layer, form
validation or anything else where different libraries already exist that can
handle that. Instead, Flask supports extensions to add such functionality to
your application as if it was implemented in Flask itself. Numerous extensions
provide database integration, form validation, upload handling, various open
authentication technologies, and more. Flask may be “micro”, but its ready for
production use on a variety of needs.</p>
<p>Why does Flask call itself a microframework and yet it depends on two
libraries (namely Werkzeug and Jinja2). Why shouldnt it? If we look
over to the Ruby side of web development there we have a protocol very
similar to WSGI. Just that its called Rack there, but besides that it
looks very much like a WSGI rendition for Ruby. But nearly all
applications in Ruby land do not work with Rack directly, but on top of a
library with the same name. This Rack library has two equivalents in
Python: WebOb (formerly Paste) and Werkzeug. Paste is still around but
from my understanding its sort of deprecated in favour of WebOb. The
development of WebOb and Werkzeug started side by side with similar ideas
in mind: be a good implementation of WSGI for other applications to take
advantage.</p>
<p>Flask is a framework that takes advantage of the work already done by
Werkzeug to properly interface WSGI (which can be a complex task at
times). Thanks to recent developments in the Python package
infrastructure, packages with dependencies are no longer an issue and
there are very few reasons against having libraries that depend on others.</p>
</section>
<section id="thread-locals">
<h2>Thread Locals<a class="headerlink" href="#thread-locals" title="Link to this heading"></a></h2>
<p>Flask uses thread local objects (context local objects in fact, they
support greenlet contexts as well) for request, session and an extra
object you can put your own things on (<a class="reference internal" href="api.html#flask.g" title="flask.g"><code class="xref py py-data docutils literal notranslate"><span class="pre">g</span></code></a>). Why is that and
isnt that a bad idea?</p>
<p>Yes it is usually not such a bright idea to use thread locals. They cause
troubles for servers that are not based on the concept of threads and make
large applications harder to maintain. However Flask is just not designed
for large applications or asynchronous servers. Flask wants to make it
quick and easy to write a traditional web application.</p>
</section>
<section id="async-await-and-asgi-support">
<h2>Async/await and ASGI support<a class="headerlink" href="#async-await-and-asgi-support" title="Link to this heading"></a></h2>
<p>Flask supports <code class="docutils literal notranslate"><span class="pre">async</span></code> coroutines for view functions by executing the
coroutine on a separate thread instead of using an event loop on the
main thread as an async-first (ASGI) framework would. This is necessary
for Flask to remain backwards compatible with extensions and code built
before <code class="docutils literal notranslate"><span class="pre">async</span></code> was introduced into Python. This compromise introduces
a performance cost compared with the ASGI frameworks, due to the
overhead of the threads.</p>
<p>Due to how tied to WSGI Flasks code is, its not clear if its possible
to make the <code class="docutils literal notranslate"><span class="pre">Flask</span></code> class support ASGI and WSGI at the same time. Work
is currently being done in Werkzeug to work with ASGI, which may
eventually enable support in Flask as well.</p>
<p>See <a class="reference internal" href="async-await.html"><span class="doc">Using async and await</span></a> for more discussion.</p>
</section>
<section id="what-flask-is-what-flask-is-not">
<h2>What Flask is, What Flask is Not<a class="headerlink" href="#what-flask-is-what-flask-is-not" title="Link to this heading"></a></h2>
<p>Flask will never have a database layer. It will not have a form library
or anything else in that direction. Flask itself just bridges to Werkzeug
to implement a proper WSGI application and to Jinja2 to handle templating.
It also binds to a few common standard library packages such as logging.
Everything else is up for extensions.</p>
<p>Why is this the case? Because people have different preferences and
requirements and Flask could not meet those if it would force any of this
into the core. The majority of web applications will need a template
engine in some sort. However not every application needs a SQL database.</p>
<p>As your codebase grows, you are free to make the design decisions appropriate
for your project. Flask will continue to provide a very simple glue layer to
the best that Python has to offer. You can implement advanced patterns in
SQLAlchemy or another database tool, introduce non-relational data persistence
as appropriate, and take advantage of framework-agnostic tools built for WSGI,
the Python web interface.</p>
<p>The idea of Flask is to build a good foundation for all applications.
Everything else is up to you or extensions.</p>
</section>
</section>
@ -81,28 +247,39 @@ issue if you get this configuration wrong.</p>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
<p class="logo"><a href="index.html">
<img class="logo" src="_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Design Decisions in Flask</a><ul>
<li><a class="reference internal" href="#the-explicit-application-object">The Explicit Application Object</a></li>
<li><a class="reference internal" href="#the-routing-system">The Routing System</a></li>
<li><a class="reference internal" href="#one-template-engine">One Template Engine</a></li>
<li><a class="reference internal" href="#what-does-micro-mean">What does “micro” mean?</a></li>
<li><a class="reference internal" href="#thread-locals">Thread Locals</a></li>
<li><a class="reference internal" href="#async-await-and-asgi-support">Async/await and ASGI support</a></li>
<li><a class="reference internal" href="#what-flask-is-what-flask-is-not">What Flask is, What Flask is Not</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<li><a href="index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="asgi.html" title="previous chapter">ASGI</a>
<li>Next: <a href="nginx.html" title="next chapter">nginx</a></ul>
</li>
<li>Previous: <a href="api.html" title="previous chapter">API</a>
<li>Next: <a href="extensiondev.html" title="next chapter">Flask Extension Development</a>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<form class="search" action="search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
@ -118,4 +295,4 @@ issue if you get this configuration wrong.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -1,164 +1,487 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<html lang="en" data-content_root="./">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>uWSGI &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="gevent" href="gevent.html" />
<link rel="prev" title="mod_wsgi" href="mod_wsgi.html" />
<title>Handling Application Errors &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="_static/flask.css?v=b87c8d14" />
<script src="_static/documentation_options.js?v=56528222"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Debugging Application Errors" href="debugging.html" />
<link rel="prev" title="Testing Flask Applications" href="testing.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="gevent.html" title="gevent"
<a href="debugging.html" title="Debugging Application Errors"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="mod_wsgi.html" title="mod_wsgi"
<a href="testing.html" title="Testing Flask Applications"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">uWSGI</a></li>
<li class="nav-item nav-item-0"><a href="index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Handling Application Errors</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="uwsgi">
<h1>uWSGI<a class="headerlink" href="#uwsgi" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/">uWSGI</a> is a fast, compiled server suite with extensive configuration
and capabilities beyond a basic server.</p>
<section id="handling-application-errors">
<h1>Handling Application Errors<a class="headerlink" href="#handling-application-errors" title="Link to this heading"></a></h1>
<p>Applications fail, servers fail. Sooner or later you will see an exception
in production. Even if your code is 100% correct, you will still see
exceptions from time to time. Why? Because everything else involved will
fail. Here are some situations where perfectly fine code can lead to server
errors:</p>
<ul class="simple">
<li><p>It can be very performant due to being a compiled program.</p></li>
<li><p>It is complex to configure beyond the basic application, and has so
many options that it can be difficult for beginners to understand.</p></li>
<li><p>It does not support Windows (but does run on WSL).</p></li>
<li><p>It requires a compiler to install in some cases.</p></li>
<li><p>the client terminated the request early and the application was still
reading from the incoming data</p></li>
<li><p>the database server was overloaded and could not handle the query</p></li>
<li><p>a filesystem is full</p></li>
<li><p>a harddrive crashed</p></li>
<li><p>a backend server overloaded</p></li>
<li><p>a programming error in a library you are using</p></li>
<li><p>network connection of the server to another system failed</p></li>
</ul>
<p>This page outlines the basics of running uWSGI. Be sure to read its
documentation to understand what features are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>uWSGI has multiple ways to install it. The most straightforward is to
install the <code class="docutils literal notranslate"><span class="pre">pyuwsgi</span></code> package, which provides precompiled wheels for
common platforms. However, it does not provide SSL support, which can be
provided with a reverse proxy instead.</p>
<p>Create a virtualenv, install your application, then install <code class="docutils literal notranslate"><span class="pre">pyuwsgi</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install pyuwsgi
<p>And thats just a small sample of issues you could be facing. So how do we
deal with that sort of problem? By default if your application runs in
production mode, and an exception is raised Flask will display a very simple
page for you and log the exception to the <a class="reference internal" href="api.html#flask.Flask.logger" title="flask.Flask.logger"><code class="xref py py-attr docutils literal notranslate"><span class="pre">logger</span></code></a>.</p>
<p>But there is more you can do, and we will cover some better setups to deal
with errors including custom exceptions and 3rd party tools.</p>
<section id="error-logging-tools">
<span id="id1"></span><h2>Error Logging Tools<a class="headerlink" href="#error-logging-tools" title="Link to this heading"></a></h2>
<p>Sending error mails, even if just for critical ones, can become
overwhelming if enough users are hitting the error and log files are
typically never looked at. This is why we recommend using <a class="reference external" href="https://sentry.io/">Sentry</a> for dealing with application errors. Its
available as a source-available project <a class="reference external" href="https://github.com/getsentry/sentry">on GitHub</a> and is also available as a <a class="reference external" href="https://sentry.io/signup/">hosted version</a> which you can try for free. Sentry
aggregates duplicate errors, captures the full stack trace and local
variables for debugging, and sends you mails based on new errors or
frequency thresholds.</p>
<p>To use Sentry you need to install the <code class="docutils literal notranslate"><span class="pre">sentry-sdk</span></code> client with extra
<code class="docutils literal notranslate"><span class="pre">flask</span></code> dependencies.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install sentry-sdk[flask]
</pre></div>
</div>
<p>If you have a compiler available, you can install the <code class="docutils literal notranslate"><span class="pre">uwsgi</span></code> package
instead. Or install the <code class="docutils literal notranslate"><span class="pre">pyuwsgi</span></code> package from sdist instead of wheel.
Either method will include SSL support.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install uwsgi
<p>And then add this to your Flask app:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">sentry_sdk</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sentry_sdk.integrations.flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">FlaskIntegration</span>
# or
$ pip install --no-binary pyuwsgi pyuwsgi
<span class="n">sentry_sdk</span><span class="o">.</span><span class="n">init</span><span class="p">(</span><span class="s1">&#39;YOUR_DSN_HERE&#39;</span><span class="p">,</span> <span class="n">integrations</span><span class="o">=</span><span class="p">[</span><span class="n">FlaskIntegration</span><span class="p">()])</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">YOUR_DSN_HERE</span></code> value needs to be replaced with the DSN value you
get from your Sentry installation.</p>
<p>After installation, failures leading to an Internal Server Error
are automatically reported to Sentry and from there you can
receive error notifications.</p>
<p>See also:</p>
<ul class="simple">
<li><p>Sentry also supports catching errors from a worker queue
(RQ, Celery, etc.) in a similar fashion. See the <a class="reference external" href="https://docs.sentry.io/platforms/python/">Python SDK docs</a> for more information.</p></li>
<li><p><a class="reference external" href="https://docs.sentry.io/platforms/python/guides/flask/">Flask-specific documentation</a></p></li>
</ul>
</section>
<section id="error-handlers">
<h2>Error Handlers<a class="headerlink" href="#error-handlers" title="Link to this heading"></a></h2>
<p>When an error occurs in Flask, an appropriate <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status">HTTP status code</a> will be
returned. 400-499 indicate errors with the clients request data, or
about the data requested. 500-599 indicate errors with the server or
application itself.</p>
<p>You might want to show custom error pages to the user when an error occurs.
This can be done by registering error handlers.</p>
<p>An error handler is a function that returns a response when a type of error is
raised, similar to how a view is a function that returns a response when a
request URL is matched. It is passed the instance of the error being handled,
which is most likely a <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPException</span></code></a>.</p>
<p>The status code of the response will not be set to the handlers code. Make
sure to provide the appropriate HTTP status code when returning a response from
a handler.</p>
<section id="registering">
<h3>Registering<a class="headerlink" href="#registering" title="Link to this heading"></a></h3>
<p>Register handlers by decorating a function with
<a class="reference internal" href="api.html#flask.Flask.errorhandler" title="flask.Flask.errorhandler"><code class="xref py py-meth docutils literal notranslate"><span class="pre">errorhandler()</span></code></a>. Or use
<a class="reference internal" href="api.html#flask.Flask.register_error_handler" title="flask.Flask.register_error_handler"><code class="xref py py-meth docutils literal notranslate"><span class="pre">register_error_handler()</span></code></a> to register the function later.
Remember to set the error code when returning the response.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="n">werkzeug</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">BadRequest</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">handle_bad_request</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="k">return</span> <span class="s1">&#39;bad request!&#39;</span><span class="p">,</span> <span class="mi">400</span>
<span class="c1"># or, without the decorator</span>
<span class="n">app</span><span class="o">.</span><span class="n">register_error_handler</span><span class="p">(</span><span class="mi">400</span><span class="p">,</span> <span class="n">handle_bad_request</span><span class="p">)</span>
</pre></div>
</div>
<p><a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">werkzeug.exceptions.HTTPException</span></code></a> subclasses like
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.BadRequest" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">BadRequest</span></code></a> and their HTTP codes are interchangeable
when registering handlers. (<code class="docutils literal notranslate"><span class="pre">BadRequest.code</span> <span class="pre">==</span> <span class="pre">400</span></code>)</p>
<p>Non-standard HTTP codes cannot be registered by code because they are not known
by Werkzeug. Instead, define a subclass of
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">HTTPException</span></code></a> with the appropriate code and
register and raise that exception class.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">InsufficientStorage</span><span class="p">(</span><span class="n">werkzeug</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">HTTPException</span><span class="p">):</span>
<span class="n">code</span> <span class="o">=</span> <span class="mi">507</span>
<span class="n">description</span> <span class="o">=</span> <span class="s1">&#39;Not enough storage space.&#39;</span>
<span class="n">app</span><span class="o">.</span><span class="n">register_error_handler</span><span class="p">(</span><span class="n">InsufficientStorage</span><span class="p">,</span> <span class="n">handle_507</span><span class="p">)</span>
<span class="k">raise</span> <span class="n">InsufficientStorage</span><span class="p">()</span>
</pre></div>
</div>
<p>Handlers can be registered for any exception class, not just
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPException</span></code></a> subclasses or HTTP status
codes. Handlers can be registered for a specific class, or for all subclasses
of a parent class.</p>
</section>
<section id="handling">
<h3>Handling<a class="headerlink" href="#handling" title="Link to this heading"></a></h3>
<p>When building a Flask application you <em>will</em> run into exceptions. If some part
of your code breaks while handling a request (and you have no error handlers
registered), a “500 Internal Server Error”
(<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.InternalServerError" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">InternalServerError</span></code></a>) will be returned by default.
Similarly, “404 Not Found”
(<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.NotFound" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">NotFound</span></code></a>) error will occur if a request is sent to an unregistered route.
If a route receives an unallowed request method, a “405 Method Not Allowed”
(<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.MethodNotAllowed" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">MethodNotAllowed</span></code></a>) will be raised. These are all
subclasses of <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">HTTPException</span></code></a> and are provided by
default in Flask.</p>
<p>Flask gives you the ability to raise any HTTP exception registered by
Werkzeug. However, the default HTTP exceptions return simple exception
pages. You might want to show custom error pages to the user when an error occurs.
This can be done by registering error handlers.</p>
<p>When Flask catches an exception while handling a request, it is first looked up by code.
If no handler is registered for the code, Flask looks up the error by its class hierarchy; the most specific handler is chosen.
If no handler is registered, <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">HTTPException</span></code></a> subclasses show a
generic message about their code, while other exceptions are converted to a
generic “500 Internal Server Error”.</p>
<p>For example, if an instance of <a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ConnectionRefusedError" title="(in Python v3.13)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ConnectionRefusedError</span></code></a> is raised,
and a handler is registered for <a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ConnectionError" title="(in Python v3.13)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ConnectionError</span></code></a> and
<a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ConnectionRefusedError" title="(in Python v3.13)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ConnectionRefusedError</span></code></a>, the more specific <a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ConnectionRefusedError" title="(in Python v3.13)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ConnectionRefusedError</span></code></a>
handler is called with the exception instance to generate the response.</p>
<p>Handlers registered on the blueprint take precedence over those registered
globally on the application, assuming a blueprint is handling the request that
raises the exception. However, the blueprint cannot handle 404 routing errors
because the 404 occurs at the routing level before the blueprint can be
determined.</p>
</section>
<section id="generic-exception-handlers">
<h3>Generic Exception Handlers<a class="headerlink" href="#generic-exception-handlers" title="Link to this heading"></a></h3>
<p>It is possible to register error handlers for very generic base classes
such as <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> or even <code class="docutils literal notranslate"><span class="pre">Exception</span></code>. However, be aware that
these will catch more than you might expect.</p>
<p>For example, an error handler for <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> might be useful for turning
the default HTML errors pages into JSON. However, this
handler will trigger for things you dont cause directly, such as 404
and 405 errors during routing. Be sure to craft your handler carefully
so you dont lose information about the HTTP error.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">json</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.exceptions</span><span class="w"> </span><span class="kn">import</span> <span class="n">HTTPException</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="n">HTTPException</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">handle_exception</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Return JSON instead of HTML for HTTP errors.&quot;&quot;&quot;</span>
<span class="c1"># start with the correct headers and status code from the error</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">get_response</span><span class="p">()</span>
<span class="c1"># replace the body with JSON</span>
<span class="n">response</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">({</span>
<span class="s2">&quot;code&quot;</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">code</span><span class="p">,</span>
<span class="s2">&quot;name&quot;</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
<span class="s2">&quot;description&quot;</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">description</span><span class="p">,</span>
<span class="p">})</span>
<span class="n">response</span><span class="o">.</span><span class="n">content_type</span> <span class="o">=</span> <span class="s2">&quot;application/json&quot;</span>
<span class="k">return</span> <span class="n">response</span>
</pre></div>
</div>
<p>An error handler for <code class="docutils literal notranslate"><span class="pre">Exception</span></code> might seem useful for changing how
all errors, even unhandled ones, are presented to the user. However,
this is similar to doing <code class="docutils literal notranslate"><span class="pre">except</span> <span class="pre">Exception:</span></code> in Python, it will
capture <em>all</em> otherwise unhandled errors, including all HTTP status
codes.</p>
<p>In most cases it will be safer to register handlers for more
specific exceptions. Since <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> instances are valid WSGI
responses, you could also pass them through directly.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.exceptions</span><span class="w"> </span><span class="kn">import</span> <span class="n">HTTPException</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="ne">Exception</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">handle_exception</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="c1"># pass through HTTP errors</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">HTTPException</span><span class="p">):</span>
<span class="k">return</span> <span class="n">e</span>
<span class="c1"># now you&#39;re handling non-HTTP exceptions only</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">&quot;500_generic.html&quot;</span><span class="p">,</span> <span class="n">e</span><span class="o">=</span><span class="n">e</span><span class="p">),</span> <span class="mi">500</span>
</pre></div>
</div>
<p>Error handlers still respect the exception class hierarchy. If you
register handlers for both <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> and <code class="docutils literal notranslate"><span class="pre">Exception</span></code>, the
<code class="docutils literal notranslate"><span class="pre">Exception</span></code> handler will not handle <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> subclasses
because the <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> handler is more specific.</p>
</section>
<section id="unhandled-exceptions">
<h3>Unhandled Exceptions<a class="headerlink" href="#unhandled-exceptions" title="Link to this heading"></a></h3>
<p>When there is no error handler registered for an exception, a 500
Internal Server Error will be returned instead. See
<a class="reference internal" href="api.html#flask.Flask.handle_exception" title="flask.Flask.handle_exception"><code class="xref py py-meth docutils literal notranslate"><span class="pre">flask.Flask.handle_exception()</span></code></a> for information about this
behavior.</p>
<p>If there is an error handler registered for <code class="docutils literal notranslate"><span class="pre">InternalServerError</span></code>,
this will be invoked. As of Flask 1.1.0, this error handler will always
be passed an instance of <code class="docutils literal notranslate"><span class="pre">InternalServerError</span></code>, not the original
unhandled error.</p>
<p>The original error is available as <code class="docutils literal notranslate"><span class="pre">e.original_exception</span></code>.</p>
<p>An error handler for “500 Internal Server Error” will be passed uncaught
exceptions in addition to explicit 500 errors. In debug mode, a handler
for “500 Internal Server Error” will not be used. Instead, the
interactive debugger will be shown.</p>
</section>
</section>
<section id="custom-error-pages">
<h2>Custom Error Pages<a class="headerlink" href="#custom-error-pages" title="Link to this heading"></a></h2>
<p>Sometimes when building a Flask application, you might want to raise a
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPException</span></code></a> to signal to the user that
something is wrong with the request. Fortunately, Flask comes with a handy
<a class="reference internal" href="api.html#flask.abort" title="flask.abort"><code class="xref py py-func docutils literal notranslate"><span class="pre">abort()</span></code></a> function that aborts a request with a HTTP error from
werkzeug as desired. It will also provide a plain black and white error page
for you with a basic description, but nothing fancy.</p>
<p>Depending on the error code it is less or more likely for the user to
actually see such an error.</p>
<p>Consider the code below, we might have a user profile route, and if the user
fails to pass a username we can raise a “400 Bad Request”. If the user passes a
username and we cant find it, we raise a “404 Not Found”.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">abort</span><span class="p">,</span> <span class="n">render_template</span><span class="p">,</span> <span class="n">request</span>
<span class="c1"># a username needs to be supplied in the query args</span>
<span class="c1"># a successful request would be like /profile?username=jack</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/profile&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user_profile</span><span class="p">():</span>
<span class="n">username</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">arg</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;username&quot;</span><span class="p">)</span>
<span class="c1"># if a username isn&#39;t supplied in the request, return a 400 bad request</span>
<span class="k">if</span> <span class="n">username</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">abort</span><span class="p">(</span><span class="mi">400</span><span class="p">)</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">get_user</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="n">username</span><span class="p">)</span>
<span class="c1"># if a user can&#39;t be found by their username, return 404 not found</span>
<span class="k">if</span> <span class="n">user</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">abort</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">&quot;profile.html&quot;</span><span class="p">,</span> <span class="n">user</span><span class="o">=</span><span class="n">user</span><span class="p">)</span>
</pre></div>
</div>
<p>Here is another example implementation for a “404 Page Not Found” exception:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">render_template</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">page_not_found</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="c1"># note that we set the 404 status explicitly</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;404.html&#39;</span><span class="p">),</span> <span class="mi">404</span>
</pre></div>
</div>
<p>When using <a class="reference internal" href="patterns/appfactories.html"><span class="doc">Application Factories</span></a>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">render_template</span>
<span class="k">def</span><span class="w"> </span><span class="nf">page_not_found</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;404.html&#39;</span><span class="p">),</span> <span class="mi">404</span>
<span class="k">def</span><span class="w"> </span><span class="nf">create_app</span><span class="p">(</span><span class="n">config_filename</span><span class="p">):</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">register_error_handler</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span> <span class="n">page_not_found</span><span class="p">)</span>
<span class="k">return</span> <span class="n">app</span>
</pre></div>
</div>
<p>An example template might be this:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">&quot;layout.html&quot;</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">title</span> <span class="cp">%}</span>Page Not Found<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">body</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Page Not Found<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>What you were looking for is just not there.
<span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">&#39;index&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>go somewhere nice<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
<section id="further-examples">
<h3>Further Examples<a class="headerlink" href="#further-examples" title="Link to this heading"></a></h3>
<p>The above examples wouldnt actually be an improvement on the default
exception pages. We can create a custom 500.html template like this:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">&quot;layout.html&quot;</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">title</span> <span class="cp">%}</span>Internal Server Error<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">body</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Internal Server Error<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>Oops... we seem to have made a mistake, sorry!<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">&#39;index&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>Go somewhere nice instead<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>It can be implemented by rendering the template on “500 Internal Server Error”:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">render_template</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">internal_server_error</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="c1"># note that we set the 500 status explicitly</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;500.html&#39;</span><span class="p">),</span> <span class="mi">500</span>
</pre></div>
</div>
<p>When using <a class="reference internal" href="patterns/appfactories.html"><span class="doc">Application Factories</span></a>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">render_template</span>
<span class="k">def</span><span class="w"> </span><span class="nf">internal_server_error</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;500.html&#39;</span><span class="p">),</span> <span class="mi">500</span>
<span class="k">def</span><span class="w"> </span><span class="nf">create_app</span><span class="p">():</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">register_error_handler</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="n">internal_server_error</span><span class="p">)</span>
<span class="k">return</span> <span class="n">app</span>
</pre></div>
</div>
<p>When using <a class="reference internal" href="blueprints.html"><span class="doc">Modular Applications with Blueprints</span></a>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">Blueprint</span>
<span class="n">blog</span> <span class="o">=</span> <span class="n">Blueprint</span><span class="p">(</span><span class="s1">&#39;blog&#39;</span><span class="p">,</span> <span class="vm">__name__</span><span class="p">)</span>
<span class="c1"># as a decorator</span>
<span class="nd">@blog</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">internal_server_error</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;500.html&#39;</span><span class="p">),</span> <span class="mi">500</span>
<span class="c1"># or with register_error_handler</span>
<span class="n">blog</span><span class="o">.</span><span class="n">register_error_handler</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="n">internal_server_error</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The most basic way to run uWSGI is to tell it to start an HTTP server
and import your application.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w hello:app
*** Starting uWSGI 2.0.20 (64bit) on [x] ***
*** Operational MODE: preforking ***
mounting hello:app on /
spawned uWSGI master process (pid: x)
spawned uWSGI worker 1 (pid: x, cores: 1)
spawned uWSGI worker 2 (pid: x, cores: 1)
spawned uWSGI worker 3 (pid: x, cores: 1)
spawned uWSGI worker 4 (pid: x, cores: 1)
spawned uWSGI http 1 (pid: x)
</pre></div>
</div>
<p>If youre using the app factory pattern, youll need to create a small
Python file to create the app, then point uWSGI at that.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text"><code class="docutils literal notranslate"><span class="pre">wsgi.py</span></code></span><a class="headerlink" href="#id2" title="Link to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">hello</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 127.0.0.1:8000 --master -p 4 -w wsgi:app
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">--http</span></code> option starts an HTTP server at 127.0.0.1 port 8000. The
<code class="docutils literal notranslate"><span class="pre">--master</span></code> option specifies the standard worker manager. The <code class="docutils literal notranslate"><span class="pre">-p</span></code>
option starts 4 worker processes; a starting value could be <code class="docutils literal notranslate"><span class="pre">CPU</span> <span class="pre">*</span> <span class="pre">2</span></code>.
The <code class="docutils literal notranslate"><span class="pre">-w</span></code> option tells uWSGI how to import your application</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>uWSGI should not be run as root with the configuration shown in this doc
because it would cause your application code to run as root, which is
not secure. However, this means it will not be possible to bind to port
80 or 443. Instead, a reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or
<a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used in front of uWSGI. It is possible to
run uWSGI as root securely, but that is beyond the scope of this doc.</p>
<p>uWSGI has optimized integration with <a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/Nginx.html">Nginx uWSGI</a> and
<a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/Apache.html#mod-proxy-uwsgi">Apache mod_proxy_uwsgi</a>, and possibly other servers, instead of using
a standard HTTP proxy. That configuration is beyond the scope of this
doc, see the links for more information.</p>
<p>You can bind to all external IPs on a non-privileged port using the
<code class="docutils literal notranslate"><span class="pre">--http</span> <span class="pre">0.0.0.0:8000</span></code> option. Dont do this when using a reverse proxy
setup, otherwise it will be possible to bypass the proxy.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 0.0.0.0:8000 --master -p 4 -w wsgi:app
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
</section>
<section id="async-with-gevent">
<h2>Async with gevent<a class="headerlink" href="#async-with-gevent" title="Link to this heading"></a></h2>
<p>The default sync worker is appropriate for many use cases. If you need
asynchronous support, uWSGI provides a <a class="reference external" href="https://www.gevent.org/">gevent</a> worker. This is not the
same as Pythons <code class="docutils literal notranslate"><span class="pre">async/await</span></code>, or the ASGI server spec. You must
actually use gevent in your own code to see any benefit to using the
worker.</p>
<p>When using gevent, greenlet&gt;=1.0 is required, otherwise context locals
such as <code class="docutils literal notranslate"><span class="pre">request</span></code> will not work as expected. When using PyPy,
PyPy&gt;=7.3.7 is required.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ uwsgi --http 127.0.0.1:8000 --master --gevent 100 -w wsgi:app
<section id="blueprint-error-handlers">
<h2>Blueprint Error Handlers<a class="headerlink" href="#blueprint-error-handlers" title="Link to this heading"></a></h2>
<p>In <a class="reference internal" href="blueprints.html"><span class="doc">Modular Applications with Blueprints</span></a>, most error handlers will work as expected.
However, there is a caveat concerning handlers for 404 and 405
exceptions. These error handlers are only invoked from an appropriate
<code class="docutils literal notranslate"><span class="pre">raise</span></code> statement or a call to <code class="docutils literal notranslate"><span class="pre">abort</span></code> in another of the blueprints
view functions; they are not invoked by, e.g., an invalid URL access.</p>
<p>This is because the blueprint does not “own” a certain URL space, so
the application instance has no way of knowing which blueprint error
handler it should run if given an invalid URL. If you would like to
execute different handling strategies for these errors based on URL
prefixes, they may be defined at the application level using the
<code class="docutils literal notranslate"><span class="pre">request</span></code> proxy object.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">jsonify</span><span class="p">,</span> <span class="n">render_template</span>
*** Starting uWSGI 2.0.20 (64bit) on [x] ***
*** Operational MODE: async ***
mounting hello:app on /
spawned uWSGI master process (pid: x)
spawned uWSGI worker 1 (pid: x, cores: 100)
spawned uWSGI http 1 (pid: x)
*** running gevent loop engine [addr:x] ***
<span class="c1"># at the application level</span>
<span class="c1"># not the blueprint level</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">page_not_found</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="c1"># if a request is in our blog URL space</span>
<span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;/blog/&#39;</span><span class="p">):</span>
<span class="c1"># we return a custom blog 404 page</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">&quot;blog/404.html&quot;</span><span class="p">),</span> <span class="mi">404</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># otherwise we return our generic site-wide 404 page</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">&quot;404.html&quot;</span><span class="p">),</span> <span class="mi">404</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">405</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">method_not_allowed</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="c1"># if a request has the wrong method to our API</span>
<span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;/api/&#39;</span><span class="p">):</span>
<span class="c1"># we return a json saying so</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">message</span><span class="o">=</span><span class="s2">&quot;Method Not Allowed&quot;</span><span class="p">),</span> <span class="mi">405</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># otherwise we return a generic site-wide 405 page</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">&quot;405.html&quot;</span><span class="p">),</span> <span class="mi">405</span>
</pre></div>
</div>
</section>
<section id="returning-api-errors-as-json">
<h2>Returning API Errors as JSON<a class="headerlink" href="#returning-api-errors-as-json" title="Link to this heading"></a></h2>
<p>When building APIs in Flask, some developers realise that the built-in
exceptions are not expressive enough for APIs and that the content type of
<em class="mimetype">text/html</em> they are emitting is not very useful for API consumers.</p>
<p>Using the same techniques as above and <a class="reference internal" href="api.html#flask.json.jsonify" title="flask.json.jsonify"><code class="xref py py-func docutils literal notranslate"><span class="pre">jsonify()</span></code></a> we can return JSON
responses to API errors. <a class="reference internal" href="api.html#flask.abort" title="flask.abort"><code class="xref py py-func docutils literal notranslate"><span class="pre">abort()</span></code></a> is called
with a <code class="docutils literal notranslate"><span class="pre">description</span></code> parameter. The error handler will
use that as the JSON error message, and set the status code to 404.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">abort</span><span class="p">,</span> <span class="n">jsonify</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">resource_not_found</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">error</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)),</span> <span class="mi">404</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/cheese&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_one_cheese</span><span class="p">():</span>
<span class="n">resource</span> <span class="o">=</span> <span class="n">get_resource</span><span class="p">()</span>
<span class="k">if</span> <span class="n">resource</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">abort</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Resource not found&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">resource</span><span class="p">)</span>
</pre></div>
</div>
<p>We can also create custom exception classes. For instance, we can
introduce a new custom exception for an API that can take a proper human readable message,
a status code for the error and some optional payload to give more context
for the error.</p>
<p>This is a simple example:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">jsonify</span><span class="p">,</span> <span class="n">request</span>
<span class="k">class</span><span class="w"> </span><span class="nc">InvalidAPIUsage</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="n">status_code</span> <span class="o">=</span> <span class="mi">400</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">status_code</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">payload</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">message</span> <span class="o">=</span> <span class="n">message</span>
<span class="k">if</span> <span class="n">status_code</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">status_code</span> <span class="o">=</span> <span class="n">status_code</span>
<span class="bp">self</span><span class="o">.</span><span class="n">payload</span> <span class="o">=</span> <span class="n">payload</span>
<span class="k">def</span><span class="w"> </span><span class="nf">to_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">rv</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">payload</span> <span class="ow">or</span> <span class="p">())</span>
<span class="n">rv</span><span class="p">[</span><span class="s1">&#39;message&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">message</span>
<span class="k">return</span> <span class="n">rv</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="n">InvalidAPIUsage</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">invalid_api_usage</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">to_dict</span><span class="p">()),</span> <span class="n">e</span><span class="o">.</span><span class="n">status_code</span>
<span class="c1"># an API app route for getting user information</span>
<span class="c1"># a correct request might be /api/user?user_id=420</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/api/user&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user_api</span><span class="p">(</span><span class="n">user_id</span><span class="p">):</span>
<span class="n">user_id</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">arg</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;user_id&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">user_id</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">InvalidAPIUsage</span><span class="p">(</span><span class="s2">&quot;No user id provided!&quot;</span><span class="p">)</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">get_user</span><span class="p">(</span><span class="n">user_id</span><span class="o">=</span><span class="n">user_id</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">user</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">InvalidAPIUsage</span><span class="p">(</span><span class="s2">&quot;No such user!&quot;</span><span class="p">,</span> <span class="n">status_code</span><span class="o">=</span><span class="mi">404</span><span class="p">)</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">user</span><span class="o">.</span><span class="n">to_dict</span><span class="p">())</span>
</pre></div>
</div>
<p>A view can now raise that exception with an error message. Additionally
some extra payload can be provided as a dictionary through the <code class="code docutils literal notranslate"><span class="pre">payload</span></code>
parameter.</p>
</section>
<section id="logging">
<h2>Logging<a class="headerlink" href="#logging" title="Link to this heading"></a></h2>
<p>See <a class="reference internal" href="logging.html"><span class="doc">Logging</span></a> for information about how to log exceptions, such as
by emailing them to admins.</p>
</section>
<section id="debugging">
<h2>Debugging<a class="headerlink" href="#debugging" title="Link to this heading"></a></h2>
<p>See <a class="reference internal" href="debugging.html"><span class="doc">Debugging Application Errors</span></a> for information about how to debug errors in
development and production.</p>
</section>
</section>
@ -169,39 +492,48 @@ spawned uWSGI http 1 (pid: x)
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
<p class="logo"><a href="index.html">
<img class="logo" src="_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">uWSGI</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
<li><a class="reference internal" href="#async-with-gevent">Async with gevent</a></li>
<li><a class="reference internal" href="#">Handling Application Errors</a><ul>
<li><a class="reference internal" href="#error-logging-tools">Error Logging Tools</a></li>
<li><a class="reference internal" href="#error-handlers">Error Handlers</a><ul>
<li><a class="reference internal" href="#registering">Registering</a></li>
<li><a class="reference internal" href="#handling">Handling</a></li>
<li><a class="reference internal" href="#generic-exception-handlers">Generic Exception Handlers</a></li>
<li><a class="reference internal" href="#unhandled-exceptions">Unhandled Exceptions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#custom-error-pages">Custom Error Pages</a><ul>
<li><a class="reference internal" href="#further-examples">Further Examples</a></li>
</ul>
</li>
<li><a class="reference internal" href="#blueprint-error-handlers">Blueprint Error Handlers</a></li>
<li><a class="reference internal" href="#returning-api-errors-as-json">Returning API Errors as JSON</a></li>
<li><a class="reference internal" href="#logging">Logging</a></li>
<li><a class="reference internal" href="#debugging">Debugging</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<li><a href="index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="mod_wsgi.html" title="previous chapter">mod_wsgi</a>
<li>Next: <a href="gevent.html" title="next chapter">gevent</a></ul>
</li>
<li>Previous: <a href="testing.html" title="previous chapter">Testing Flask Applications</a>
<li>Next: <a href="debugging.html" title="next chapter">Debugging Application Errors</a>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<form class="search" action="search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
@ -217,4 +549,4 @@ spawned uWSGI http 1 (pid: x)
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

View file

@ -1,108 +1,307 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<html lang="en" data-content_root="./">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Waitress &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="mod_wsgi" href="mod_wsgi.html" />
<link rel="prev" title="Gunicorn" href="gunicorn.html" />
<title>Flask Extension Development &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="_static/flask.css?v=b87c8d14" />
<script src="_static/documentation_options.js?v=56528222"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Contributing" href="contributing.html" />
<link rel="prev" title="Design Decisions in Flask" href="design.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="mod_wsgi.html" title="mod_wsgi"
<a href="contributing.html" title="Contributing"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="gunicorn.html" title="Gunicorn"
<a href="design.html" title="Design Decisions in Flask"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Deploying to Production</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Waitress</a></li>
<li class="nav-item nav-item-0"><a href="index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Flask Extension Development</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="waitress">
<h1>Waitress<a class="headerlink" href="#waitress" title="Link to this heading"></a></h1>
<p><a class="reference external" href="https://docs.pylonsproject.org/projects/waitress/">Waitress</a> is a pure Python WSGI server.</p>
<section id="flask-extension-development">
<h1>Flask Extension Development<a class="headerlink" href="#flask-extension-development" title="Link to this heading"></a></h1>
<p>Extensions are extra packages that add functionality to a Flask
application. While <a class="reference external" href="https://pypi.org/search/?c=Framework+%3A%3A+Flask">PyPI</a> contains many Flask extensions, you may not
find one that fits your need. If this is the case, you can create your
own, and publish it for others to use as well.</p>
<p>This guide will show how to create a Flask extension, and some of the
common patterns and requirements involved. Since extensions can do
anything, this guide wont be able to cover every possibility.</p>
<p>The best ways to learn about extensions are to look at how other
extensions you use are written, and discuss with others. Discuss your
design ideas with others on our <a class="reference external" href="https://discord.gg/pallets">Discord Chat</a> or
<a class="reference external" href="https://github.com/pallets/flask/discussions">GitHub Discussions</a>.</p>
<p>The best extensions share common patterns, so that anyone familiar with
using one extension wont feel completely lost with another. This can
only work if collaboration happens early.</p>
<section id="naming">
<h2>Naming<a class="headerlink" href="#naming" title="Link to this heading"></a></h2>
<p>A Flask extension typically has <code class="docutils literal notranslate"><span class="pre">flask</span></code> in its name as a prefix or
suffix. If it wraps another library, it should include the library name
as well. This makes it easy to search for extensions, and makes their
purpose clearer.</p>
<p>A general Python packaging recommendation is that the install name from
the package index and the name used in <code class="docutils literal notranslate"><span class="pre">import</span></code> statements should be
related. The import name is lowercase, with words separated by
underscores (<code class="docutils literal notranslate"><span class="pre">_</span></code>). The install name is either lower case or title
case, with words separated by dashes (<code class="docutils literal notranslate"><span class="pre">-</span></code>). If it wraps another
library, prefer using the same case as that librarys name.</p>
<p>Here are some example install and import names:</p>
<ul class="simple">
<li><p>It is easy to configure.</p></li>
<li><p>It supports Windows directly.</p></li>
<li><p>It is easy to install as it does not require additional dependencies
or compilation.</p></li>
<li><p>It does not support streaming requests, full request data is always
buffered.</p></li>
<li><p>It uses a single process with multiple thread workers.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Flask-Name</span></code> imported as <code class="docutils literal notranslate"><span class="pre">flask_name</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">flask-name-lower</span></code> imported as <code class="docutils literal notranslate"><span class="pre">flask_name_lower</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Flask-ComboName</span></code> imported as <code class="docutils literal notranslate"><span class="pre">flask_comboname</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Name-Flask</span></code> imported as <code class="docutils literal notranslate"><span class="pre">name_flask</span></code></p></li>
</ul>
<p>This page outlines the basics of running Waitress. Be sure to read its
documentation and <code class="docutils literal notranslate"><span class="pre">waitress-serve</span> <span class="pre">--help</span></code> to understand what features
are available.</p>
<section id="installing">
<h2>Installing<a class="headerlink" href="#installing" title="Link to this heading"></a></h2>
<p>Create a virtualenv, install your application, then install
<code class="docutils literal notranslate"><span class="pre">waitress</span></code>.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ cd hello-app
$ python -m venv .venv
$ . .venv/bin/activate
$ pip install . # install your application
$ pip install waitress
</section>
<section id="the-extension-class-and-initialization">
<h2>The Extension Class and Initialization<a class="headerlink" href="#the-extension-class-and-initialization" title="Link to this heading"></a></h2>
<p>All extensions will need some entry point that initializes the
extension with the application. The most common pattern is to create a
class that represents the extensions configuration and behavior, with
an <code class="docutils literal notranslate"><span class="pre">init_app</span></code> method to apply the extension instance to the given
application instance.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">HelloExtension</span><span class="p">:</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">app</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">init_app</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">):</span>
<span class="n">app</span><span class="o">.</span><span class="n">before_request</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="running">
<h2>Running<a class="headerlink" href="#running" title="Link to this heading"></a></h2>
<p>The only required argument to <code class="docutils literal notranslate"><span class="pre">waitress-serve</span></code> tells it how to load
your Flask application. The syntax is <code class="docutils literal notranslate"><span class="pre">{module}:{app}</span></code>. <code class="docutils literal notranslate"><span class="pre">module</span></code> is
the dotted import name to the module with your application. <code class="docutils literal notranslate"><span class="pre">app</span></code> is
the variable with the application. If youre using the app factory
pattern, use <code class="docutils literal notranslate"><span class="pre">--call</span> <span class="pre">{module}:{factory}</span></code> instead.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span># equivalent to &#39;from hello import app&#39;
$ waitress-serve --host 127.0.0.1 hello:app
<p>It is important that the app is not stored on the extension, dont do
<code class="docutils literal notranslate"><span class="pre">self.app</span> <span class="pre">=</span> <span class="pre">app</span></code>. The only time the extension should have direct
access to an app is during <code class="docutils literal notranslate"><span class="pre">init_app</span></code>, otherwise it should use
<a class="reference internal" href="api.html#flask.current_app" title="flask.current_app"><code class="xref py py-data docutils literal notranslate"><span class="pre">current_app</span></code></a>.</p>
<p>This allows the extension to support the application factory pattern,
avoids circular import issues when importing the extension instance
elsewhere in a users code, and makes testing with different
configurations easier.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">hello</span> <span class="o">=</span> <span class="n">HelloExtension</span><span class="p">()</span>
# equivalent to &#39;from hello import create_app; create_app()&#39;
$ waitress-serve --host 127.0.0.1 --call hello:create_app
Serving on http://127.0.0.1:8080
<span class="k">def</span><span class="w"> </span><span class="nf">create_app</span><span class="p">():</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="n">hello</span><span class="o">.</span><span class="n">init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="k">return</span> <span class="n">app</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">--host</span></code> option binds the server to local <code class="docutils literal notranslate"><span class="pre">127.0.0.1</span></code> only.</p>
<p>Logs for each request arent shown, only errors are shown. Logging can
be configured through the Python interface instead of the command line.</p>
<p>Above, the <code class="docutils literal notranslate"><span class="pre">hello</span></code> extension instance exists independently of the
application. This means that other modules in a users project can do
<code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">project</span> <span class="pre">import</span> <span class="pre">hello</span></code> and use the extension in blueprints before
the app exists.</p>
<p>The <a class="reference internal" href="api.html#flask.Flask.extensions" title="flask.Flask.extensions"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Flask.extensions</span></code></a> dict can be used to store a reference to
the extension on the application, or some other state specific to the
application. Be aware that this is a single namespace, so use a name
unique to your extension, such as the extensions name without the
“flask” prefix.</p>
</section>
<section id="binding-externally">
<h2>Binding Externally<a class="headerlink" href="#binding-externally" title="Link to this heading"></a></h2>
<p>Waitress should not be run as root because it would cause your
application code to run as root, which is not secure. However, this
means it will not be possible to bind to port 80 or 443. Instead, a
reverse proxy such as <a class="reference internal" href="nginx.html"><span class="doc">nginx</span></a> or <a class="reference internal" href="apache-httpd.html"><span class="doc">Apache httpd</span></a> should be used
in front of Waitress.</p>
<p>You can bind to all external IPs on a non-privileged port by not
specifying the <code class="docutils literal notranslate"><span class="pre">--host</span></code> option. Dont do this when using a reverse
proxy setup, otherwise it will be possible to bypass the proxy.</p>
<p><code class="docutils literal notranslate"><span class="pre">0.0.0.0</span></code> is not a valid address to navigate to, youd use a specific
IP address in your browser.</p>
<section id="adding-behavior">
<h2>Adding Behavior<a class="headerlink" href="#adding-behavior" title="Link to this heading"></a></h2>
<p>There are many ways that an extension can add behavior. Any setup
methods that are available on the <a class="reference internal" href="api.html#flask.Flask" title="flask.Flask"><code class="xref py py-class docutils literal notranslate"><span class="pre">Flask</span></code></a> object can be used
during an extensions <code class="docutils literal notranslate"><span class="pre">init_app</span></code> method.</p>
<p>A common pattern is to use <a class="reference internal" href="api.html#flask.Flask.before_request" title="flask.Flask.before_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">before_request()</span></code></a> to initialize
some data or a connection at the beginning of each request, then
<a class="reference internal" href="api.html#flask.Flask.teardown_request" title="flask.Flask.teardown_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">teardown_request()</span></code></a> to clean it up at the end. This can be
stored on <a class="reference internal" href="api.html#flask.g" title="flask.g"><code class="xref py py-data docutils literal notranslate"><span class="pre">g</span></code></a>, discussed more below.</p>
<p>A more lazy approach is to provide a method that initializes and caches
the data or connection. For example, a <code class="docutils literal notranslate"><span class="pre">ext.get_db</span></code> method could
create a database connection the first time its called, so that a view
that doesnt use the database doesnt create a connection.</p>
<p>Besides doing something before and after every view, your extension
might want to add some specific views as well. In this case, you could
define a <a class="reference internal" href="api.html#flask.Blueprint" title="flask.Blueprint"><code class="xref py py-class docutils literal notranslate"><span class="pre">Blueprint</span></code></a>, then call <a class="reference internal" href="api.html#flask.Flask.register_blueprint" title="flask.Flask.register_blueprint"><code class="xref py py-meth docutils literal notranslate"><span class="pre">register_blueprint()</span></code></a>
during <code class="docutils literal notranslate"><span class="pre">init_app</span></code> to add the blueprint to the app.</p>
</section>
<section id="configuration-techniques">
<h2>Configuration Techniques<a class="headerlink" href="#configuration-techniques" title="Link to this heading"></a></h2>
<p>There can be multiple levels and sources of configuration for an
extension. You should consider what parts of your extension fall into
each one.</p>
<ul class="simple">
<li><p>Configuration per application instance, through <code class="docutils literal notranslate"><span class="pre">app.config</span></code>
values. This is configuration that could reasonably change for each
deployment of an application. A common example is a URL to an
external resource, such as a database. Configuration keys should
start with the extensions name so that they dont interfere with
other extensions.</p></li>
<li><p>Configuration per extension instance, through <code class="docutils literal notranslate"><span class="pre">__init__</span></code>
arguments. This configuration usually affects how the extension
is used, such that it wouldnt make sense to change it per
deployment.</p></li>
<li><p>Configuration per extension instance, through instance attributes
and decorator methods. It might be more ergonomic to assign to
<code class="docutils literal notranslate"><span class="pre">ext.value</span></code>, or use a <code class="docutils literal notranslate"><span class="pre">&#64;ext.register</span></code> decorator to register a
function, after the extension instance has been created.</p></li>
<li><p>Global configuration through class attributes. Changing a class
attribute like <code class="docutils literal notranslate"><span class="pre">Ext.connection_class</span></code> can customize default
behavior without making a subclass. This could be combined
per-extension configuration to override defaults.</p></li>
<li><p>Subclassing and overriding methods and attributes. Making the API of
the extension itself something that can be overridden provides a
very powerful tool for advanced customization.</p></li>
</ul>
<p>The <a class="reference internal" href="api.html#flask.Flask" title="flask.Flask"><code class="xref py py-class docutils literal notranslate"><span class="pre">Flask</span></code></a> object itself uses all of these techniques.</p>
<p>Its up to you to decide what configuration is appropriate for your
extension, based on what you need and what you want to support.</p>
<p>Configuration should not be changed after the application setup phase is
complete and the server begins handling requests. Configuration is
global, any changes to it are not guaranteed to be visible to other
workers.</p>
</section>
<section id="data-during-a-request">
<h2>Data During a Request<a class="headerlink" href="#data-during-a-request" title="Link to this heading"></a></h2>
<p>When writing a Flask application, the <a class="reference internal" href="api.html#flask.g" title="flask.g"><code class="xref py py-data docutils literal notranslate"><span class="pre">g</span></code></a> object is used to
store information during a request. For example the
<a class="reference internal" href="tutorial/database.html"><span class="doc">tutorial</span></a> stores a connection to a SQLite
database as <code class="docutils literal notranslate"><span class="pre">g.db</span></code>. Extensions can also use this, with some care.
Since <code class="docutils literal notranslate"><span class="pre">g</span></code> is a single global namespace, extensions must use unique
names that wont collide with user data. For example, use the extension
name as a prefix, or as a namespace.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># an internal prefix with the extension name</span>
<span class="n">g</span><span class="o">.</span><span class="n">_hello_user_id</span> <span class="o">=</span> <span class="mi">2</span>
<span class="c1"># or an internal prefix as a namespace</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">types</span><span class="w"> </span><span class="kn">import</span> <span class="n">SimpleNamespace</span>
<span class="n">g</span><span class="o">.</span><span class="n">_hello</span> <span class="o">=</span> <span class="n">SimpleNamespace</span><span class="p">()</span>
<span class="n">g</span><span class="o">.</span><span class="n">_hello</span><span class="o">.</span><span class="n">user_id</span> <span class="o">=</span> <span class="mi">2</span>
</pre></div>
</div>
<p>The data in <code class="docutils literal notranslate"><span class="pre">g</span></code> lasts for an application context. An application
context is active when a request context is, or when a CLI command is
run. If youre storing something that should be closed, use
<a class="reference internal" href="api.html#flask.Flask.teardown_appcontext" title="flask.Flask.teardown_appcontext"><code class="xref py py-meth docutils literal notranslate"><span class="pre">teardown_appcontext()</span></code></a> to ensure that it gets closed
when the application context ends. If it should only be valid during a
request, or would not be used in the CLI outside a request, use
<a class="reference internal" href="api.html#flask.Flask.teardown_request" title="flask.Flask.teardown_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">teardown_request()</span></code></a>.</p>
</section>
<section id="views-and-models">
<h2>Views and Models<a class="headerlink" href="#views-and-models" title="Link to this heading"></a></h2>
<p>Your extension views might want to interact with specific models in your
database, or some other extension or data connected to your application.
For example, lets consider a <code class="docutils literal notranslate"><span class="pre">Flask-SimpleBlog</span></code> extension that works
with Flask-SQLAlchemy to provide a <code class="docutils literal notranslate"><span class="pre">Post</span></code> model and views to write
and read posts.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">Post</span></code> model needs to subclass the Flask-SQLAlchemy <code class="docutils literal notranslate"><span class="pre">db.Model</span></code>
object, but thats only available once youve created an instance of
that extension, not when your extension is defining its views. So how
can the view code, defined before the model exists, access the model?</p>
<p>One method could be to use <a class="reference internal" href="views.html"><span class="doc">Class-based Views</span></a>. During <code class="docutils literal notranslate"><span class="pre">__init__</span></code>, create
the model, then create the views by passing the model to the view
classs <a class="reference internal" href="api.html#flask.views.View.as_view" title="flask.views.View.as_view"><code class="xref py py-meth docutils literal notranslate"><span class="pre">as_view()</span></code></a> method.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">PostAPI</span><span class="p">(</span><span class="n">MethodView</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">model</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">model</span> <span class="o">=</span> <span class="n">model</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">id</span><span class="p">):</span>
<span class="n">post</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">post</span><span class="o">.</span><span class="n">to_json</span><span class="p">())</span>
<span class="k">class</span><span class="w"> </span><span class="nc">BlogExtension</span><span class="p">:</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">db</span><span class="p">):</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Post</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
<span class="nb">id</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">title</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">db</span><span class="o">.</span><span class="n">String</span><span class="p">,</span> <span class="n">nullable</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">post_model</span> <span class="o">=</span> <span class="n">Post</span>
<span class="k">def</span><span class="w"> </span><span class="nf">init_app</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">):</span>
<span class="n">api_view</span> <span class="o">=</span> <span class="n">PostAPI</span><span class="o">.</span><span class="n">as_view</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">post_model</span><span class="p">)</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">SQLAlchemy</span><span class="p">()</span>
<span class="n">blog</span> <span class="o">=</span> <span class="n">BlogExtension</span><span class="p">(</span><span class="n">db</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="n">blog</span><span class="o">.</span><span class="n">init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
</pre></div>
</div>
<p>Another technique could be to use an attribute on the extension, such as
<code class="docutils literal notranslate"><span class="pre">self.post_model</span></code> from above. Add the extension to <code class="docutils literal notranslate"><span class="pre">app.extensions</span></code>
in <code class="docutils literal notranslate"><span class="pre">init_app</span></code>, then access
<code class="docutils literal notranslate"><span class="pre">current_app.extensions[&quot;simple_blog&quot;].post_model</span></code> from views.</p>
<p>You may also want to provide base classes so that users can provide
their own <code class="docutils literal notranslate"><span class="pre">Post</span></code> model that conforms to the API your extension
expects. So they could implement <code class="docutils literal notranslate"><span class="pre">class</span> <span class="pre">Post(blog.BasePost)</span></code>, then
set it as <code class="docutils literal notranslate"><span class="pre">blog.post_model</span></code>.</p>
<p>As you can see, this can get a bit complex. Unfortunately, theres no
perfect solution here, only different strategies and tradeoffs depending
on your needs and how much customization you want to offer. Luckily,
this sort of resource dependency is not a common need for most
extensions. Remember, if you need help with design, ask on our
<a class="reference external" href="https://discord.gg/pallets">Discord Chat</a> or <a class="reference external" href="https://github.com/pallets/flask/discussions">GitHub Discussions</a>.</p>
</section>
<section id="recommended-extension-guidelines">
<h2>Recommended Extension Guidelines<a class="headerlink" href="#recommended-extension-guidelines" title="Link to this heading"></a></h2>
<p>Flask previously had the concept of “approved extensions”, where the
Flask maintainers evaluated the quality, support, and compatibility of
the extensions before listing them. While the list became too difficult
to maintain over time, the guidelines are still relevant to all
extensions maintained and developed today, as they help the Flask
ecosystem remain consistent and compatible.</p>
<ol class="arabic simple">
<li><p>An extension requires a maintainer. In the event an extension author
would like to move beyond the project, the project should find a new
maintainer and transfer access to the repository, documentation,
PyPI, and any other services. The <a class="reference external" href="https://github.com/pallets-eco">Pallets-Eco</a> organization on
GitHub allows for community maintenance with oversight from the
Pallets maintainers.</p></li>
<li><p>The naming scheme is <em>Flask-ExtensionName</em> or <em>ExtensionName-Flask</em>.
It must provide exactly one package or module named
<code class="docutils literal notranslate"><span class="pre">flask_extension_name</span></code>.</p></li>
<li><p>The extension must use an open source license. The Python web
ecosystem tends to prefer BSD or MIT. It must be open source and
publicly available.</p></li>
<li><p>The extensions API must have the following characteristics:</p>
<ul class="simple">
<li><p>It must support multiple applications running in the same Python
process. Use <code class="docutils literal notranslate"><span class="pre">current_app</span></code> instead of <code class="docutils literal notranslate"><span class="pre">self.app</span></code>, store
configuration and state per application instance.</p></li>
<li><p>It must be possible to use the factory pattern for creating
applications. Use the <code class="docutils literal notranslate"><span class="pre">ext.init_app()</span></code> pattern.</p></li>
</ul>
</li>
<li><p>From a clone of the repository, an extension with its dependencies
must be installable in editable mode with <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">-e</span> <span class="pre">.</span></code>.</p></li>
<li><p>It must ship tests that can be invoked with a common tool like
<code class="docutils literal notranslate"><span class="pre">tox</span> <span class="pre">-e</span> <span class="pre">py</span></code>, <code class="docutils literal notranslate"><span class="pre">nox</span> <span class="pre">-s</span> <span class="pre">test</span></code> or <code class="docutils literal notranslate"><span class="pre">pytest</span></code>. If not using <code class="docutils literal notranslate"><span class="pre">tox</span></code>,
the test dependencies should be specified in a requirements file.
The tests must be part of the sdist distribution.</p></li>
<li><p>A link to the documentation or project website must be in the PyPI
metadata or the readme. The documentation should use the Flask theme
from the <a class="reference external" href="https://pypi.org/project/Pallets-Sphinx-Themes/">Official Pallets Themes</a>.</p></li>
<li><p>The extensions dependencies should not use upper bounds or assume
any particular version scheme, but should use lower bounds to
indicate minimum compatibility support. For example,
<code class="docutils literal notranslate"><span class="pre">sqlalchemy&gt;=1.4</span></code>.</p></li>
<li><p>Indicate the versions of Python supported using <code class="docutils literal notranslate"><span class="pre">python_requires=&quot;&gt;=version&quot;</span></code>.
Flask itself supports Python &gt;=3.9 as of October 2024, and this will update
over time.</p></li>
</ol>
</section>
</section>
@ -114,38 +313,39 @@ IP address in your browser.</p>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
<p class="logo"><a href="index.html">
<img class="logo" src="_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Waitress</a><ul>
<li><a class="reference internal" href="#installing">Installing</a></li>
<li><a class="reference internal" href="#running">Running</a></li>
<li><a class="reference internal" href="#binding-externally">Binding Externally</a></li>
<li><a class="reference internal" href="#">Flask Extension Development</a><ul>
<li><a class="reference internal" href="#naming">Naming</a></li>
<li><a class="reference internal" href="#the-extension-class-and-initialization">The Extension Class and Initialization</a></li>
<li><a class="reference internal" href="#adding-behavior">Adding Behavior</a></li>
<li><a class="reference internal" href="#configuration-techniques">Configuration Techniques</a></li>
<li><a class="reference internal" href="#data-during-a-request">Data During a Request</a></li>
<li><a class="reference internal" href="#views-and-models">Views and Models</a></li>
<li><a class="reference internal" href="#recommended-extension-guidelines">Recommended Extension Guidelines</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<li><a href="index.html">Overview</a>
<ul>
<li><a href="index.html">Deploying to Production</a>
<ul>
<li>Previous: <a href="gunicorn.html" title="previous chapter">Gunicorn</a>
<li>Next: <a href="mod_wsgi.html" title="next chapter">mod_wsgi</a></ul>
</li>
<li>Previous: <a href="design.html" title="previous chapter">Design Decisions in Flask</a>
<li>Next: <a href="contributing.html" title="next chapter">Contributing</a>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<form class="search" action="search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
@ -161,4 +361,4 @@ IP address in your browser.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>