## File: README.md

# Flask

Flask is a lightweight [WSGI] web application framework. It is designed
to make getting started quick and easy, with the ability to scale up to
complex applications. It began as a simple wrapper around [Werkzeug]
and [Jinja], and has become one of the most popular Python web
application frameworks.

Flask offers suggestions, but doesn't enforce any dependencies or
project layout. It is up to the developer to choose the tools and
libraries they want to use. There are many extensions provided by the
community that make adding new functionality easy.

[WSGI]: https://wsgi.readthedocs.io/
[Werkzeug]: https://werkzeug.palletsprojects.com/
[Jinja]: https://jinja.palletsprojects.com/

## A Simple Example

```python
# save this as app.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, World!"
```

```
$ flask run
  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```

## Donate

The Pallets organization develops and supports Flask and the libraries
it uses. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, [please
donate today].

[please donate today]: https://palletsprojects.com/donate

## Contributing

See our [detailed contributing documentation][contrib] for many ways to
contribute, including reporting issues, requesting features, asking or answering
questions, and making PRs.

[contrib]: https://palletsprojects.com/contributing/

---

## File: docs/deploying/apache-httpd.rst

Apache httpd
============

`Apache httpd`_ is a fast, production level HTTP server. When serving
your application with one of the WSGI servers listed in :doc:`index`, 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.

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.

.. _Apache httpd: https://httpd.apache.org/


Domain Name
-----------

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 provider's name servers.

To simulate this, you can also edit your ``hosts`` file, located at
``/etc/hosts`` on Linux. Add a line that associates a name with the
local IP.

Modern Linux systems may be configured to treat any domain name that
ends with ``.localhost`` like this without adding it to the ``hosts``
file.

.. code-block:: python
    :caption: ``/etc/hosts``

    127.0.0.1 hello.localhost


Configuration
-------------

The httpd configuration is located at ``/etc/httpd/conf/httpd.conf`` on
Linux. It may be different depending on your operating system. Check the
docs and look for ``httpd.conf``.

Remove or comment out any existing ``DocumentRoot`` directive. Add the
config lines below. We'll assume the WSGI server is listening locally at
``http://127.0.0.1:8000``.

.. code-block:: apache
    :caption: ``/etc/httpd/conf/httpd.conf``

    LoadModule proxy_module modules/mod_proxy.so
    LoadModule proxy_http_module modules/mod_proxy_http.so
    ProxyPass / http://127.0.0.1:8000/
    RequestHeader set X-Forwarded-Proto http
    RequestHeader set X-Forwarded-Prefix /

The ``LoadModule`` lines might already exist. If so, make sure they are
uncommented instead of adding them manually.

Then :doc:`proxy_fix` so that your application uses the ``X-Forwarded``
headers. ``X-Forwarded-For`` and ``X-Forwarded-Host`` are automatically
set by ``ProxyPass``.

---

## File: docs/deploying/asgi.rst

ASGI
====

If you'd like to use an ASGI server you will need to utilise WSGI to
ASGI middleware. The asgiref
`WsgiToAsgi <https://github.com/django/asgiref#wsgi-to-asgi-adapter>`_
adapter is recommended as it integrates with the event loop used for
Flask's :ref:`async_await` support. You can use the adapter by
wrapping the Flask app,

.. code-block:: python

    from asgiref.wsgi import WsgiToAsgi
    from flask import Flask

    app = Flask(__name__)

    ...

    asgi_app = WsgiToAsgi(app)

and then serving the ``asgi_app`` with the ASGI server, e.g. using
`Hypercorn <https://github.com/pgjones/hypercorn>`_,

.. sourcecode:: text

    $ hypercorn module:asgi_app

---

## File: docs/deploying/eventlet.rst

:orphan:

eventlet
========

`Eventlet is no longer maintained.`__ Use :doc:`/deploying/gevent` instead.

__ https://eventlet.readthedocs.io

---

## File: docs/deploying/gevent.rst

gevent
======

Prefer using :doc:`gunicorn` or :doc:`uwsgi` with gevent workers rather
than using `gevent`_ directly. Gunicorn and uWSGI provide much more
configurable and production-tested servers.

`gevent`_ allows writing asynchronous, coroutine-based code that looks
like standard synchronous Python. It uses `greenlet`_ to enable task
switching without writing ``async/await`` or using ``asyncio``. This is
not the same as Python's ``async/await``, or the ASGI server spec.

gevent provides a WSGI server that can handle many connections at once
instead of one per worker process. See :doc:`/gevent` for more
information about enabling it in your application.

.. _gevent: https://www.gevent.org/
.. _greenlet: https://greenlet.readthedocs.io/en/latest/


Installing
----------

When using gevent, greenlet>=1.0 is required. When using PyPy,
PyPy>=7.3.7 is required.

Create a virtualenv, install your application, then install ``gevent``.

.. code-block:: text

    $ cd hello-app
    $ python -m venv .venv
    $ . .venv/bin/activate
    $ pip install .  # install your application
    $ pip install gevent


Running
-------

To use gevent to serve your application, write a script that imports its
``WSGIServer``, as well as your app or app factory.

.. code-block:: python
    :caption: ``wsgi.py``

    from gevent.pywsgi import WSGIServer
    from hello import create_app

    app = create_app()
    http_server = WSGIServer(("127.0.0.1", 8000), app)
    http_server.serve_forever()

.. code-block:: text

    $ python wsgi.py

No output is shown when the server starts.


Binding Externally
------------------

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 :doc:`nginx` or :doc:`apache-httpd` should be used
in front of gevent.

You can bind to all external IPs on a non-privileged port by using
``0.0.0.0`` in the server arguments shown in the previous section. Don't
do this when using a reverse proxy setup, otherwise it will be possible
to bypass the proxy.

``0.0.0.0`` is not a valid address to navigate to, you'd use a specific
IP address in your browser.

---

## File: docs/deploying/gunicorn.rst

Gunicorn
========

`Gunicorn`_ is a pure Python WSGI server with simple configuration and
multiple worker implementations for performance tuning.

*   It tends to integrate easily with hosting platforms.
*   It does not support Windows (but does run on WSL).
*   It is easy to install as it does not require additional dependencies
    or compilation.
*   It has built-in async worker support using gevent.

This page outlines the basics of running Gunicorn. Be sure to read its
`documentation`_ and use ``gunicorn --help`` to understand what features
are available.

.. _Gunicorn: https://gunicorn.org/
.. _documentation: https://docs.gunicorn.org/


Installing
----------

Gunicorn is easy to install, as it does not require external
dependencies or compilation. It runs on Windows only under WSL.

Create a virtualenv, install your application, then install
``gunicorn``.

.. code-block:: text

    $ cd hello-app
    $ python -m venv .venv
    $ . .venv/bin/activate
    $ pip install .  # install your application
    $ pip install gunicorn


Running
-------

The only required argument to Gunicorn tells it how to load your Flask
application. The syntax is ``{module_import}:{app_variable}``.
``module_import`` is the dotted import name to the module with your
application. ``app_variable`` is the variable with the application. It
can also be a function call (with any arguments) if you're using the
app factory pattern.

.. code-block:: text

    # equivalent to 'from hello import app'
    $ gunicorn -w 4 'hello:app'

    # equivalent to 'from hello import create_app; create_app()'
    $ gunicorn -w 4 'hello:create_app()'

    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

The ``-w`` option specifies the number of processes to run; a starting
value could be ``CPU * 2``. The default is only 1 worker, which is
probably not what you want for the default worker type.

Logs for each request aren't shown by default, only worker info and
errors are shown. To show access logs on stdout, use the
``--access-logfile=-`` option.


Binding Externally
------------------

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 :doc:`nginx` or :doc:`apache-httpd` should be used
in front of Gunicorn.

You can bind to all external IPs on a non-privileged port using the
``-b 0.0.0.0`` option. Don't do this when using a reverse proxy setup,
otherwise it will be possible to bypass the proxy.

.. code-block:: text

    $ gunicorn -w 4 -b 0.0.0.0 'hello:create_app()'
    Listening at: http://0.0.0.0:8000 (x)

``0.0.0.0`` is not a valid address to navigate to, you'd use a specific
IP address in your browser.


Async with gevent
-----------------

The default sync worker is appropriate for most use cases. If you need numerous,
long running, concurrent connections, Gunicorn provides an asynchronous worker
using `gevent`_. This is not the same as Python's ``async/await``, or the ASGI
server spec. See :doc:`/gevent` for more information about enabling it in your
application.

.. _gevent: https://www.gevent.org/

When using gevent, greenlet>=1.0 is required. When using PyPy, PyPy>=7.3.7 is
required.

.. code-block:: text

    $ gunicorn -k gevent 'hello:create_app()'
    Starting gunicorn 20.1.0
    Listening at: http://127.0.0.1:8000 (x)
    Using worker: gevent
    Booting worker with pid: x

---

## File: docs/deploying/index.rst

Deploying to Production
=======================

After developing your application, you'll want to make it available
publicly to other users. When you're developing locally, you're 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.

"Production" means "not development", which applies whether you're
serving your application publicly to millions of users or privately /
locally to a single user. **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.**

Self-Hosted Options
-------------------

Flask is a WSGI *application*. A WSGI *server* is used to run the
application, converting incoming HTTP requests to the standard WSGI
environ, and converting outgoing WSGI responses to HTTP responses.

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.

.. toctree::
    :maxdepth: 1

    gunicorn
    waitress
    mod_wsgi
    uwsgi
    gevent
    asgi

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."

.. toctree::
    :maxdepth: 1

    proxy_fix
    nginx
    apache-httpd

This list is not exhaustive, and you should evaluate these and other
servers based on your application's needs. Different servers will have
different capabilities, configuration, and support.


Hosting Platforms
-----------------

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.

- `PythonAnywhere <https://help.pythonanywhere.com/pages/Flask/>`_
- `Google App Engine <https://cloud.google.com/appengine/docs/standard/python3/building-app>`_
- `Google Cloud Run <https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-python-service>`_
- `AWS Elastic Beanstalk <https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-flask.html>`_
- `Microsoft Azure <https://docs.microsoft.com/en-us/azure/app-service/quickstart-python>`_

This list is not exhaustive, and you should evaluate these and other
services based on your application's needs. Different services will have
different capabilities, configuration, pricing, and support.

You'll probably need to :doc:`proxy_fix` when using most hosting
platforms.

---

## File: docs/deploying/mod_wsgi.rst

mod_wsgi
========

`mod_wsgi`_ is a WSGI server integrated with the `Apache httpd`_ server.
The modern `mod_wsgi-express`_ command makes it easy to configure and
start the server without needing to write Apache httpd configuration.

*   Tightly integrated with Apache httpd.
*   Supports Windows directly.
*   Requires a compiler and the Apache development headers to install.
*   Does not require a reverse proxy setup.

This page outlines the basics of running mod_wsgi-express, not the more
complex installation and configuration with httpd. Be sure to read the
`mod_wsgi-express`_, `mod_wsgi`_, and `Apache httpd`_ documentation to
understand what features are available.

.. _mod_wsgi-express: https://pypi.org/project/mod-wsgi/
.. _mod_wsgi: https://modwsgi.readthedocs.io/
.. _Apache httpd: https://httpd.apache.org/


Installing
----------

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.

Create a virtualenv, install your application, then install
``mod_wsgi``.

.. code-block:: text

    $ cd hello-app
    $ python -m venv .venv
    $ . .venv/bin/activate
    $ pip install .  # install your application
    $ pip install mod_wsgi


Running
-------

The only argument to ``mod_wsgi-express`` specifies a script containing
your Flask application, which must be called ``application``. You can
write a small script to import your app with this name, or to create it
if using the app factory pattern.

.. code-block:: python
    :caption: ``wsgi.py``

    from hello import app

    application = app

.. code-block:: python
    :caption: ``wsgi.py``

    from hello import create_app

    application = create_app()

Now run the ``mod_wsgi-express start-server`` command.

.. code-block:: text

    $ mod_wsgi-express start-server wsgi.py --processes 4

The ``--processes`` option specifies the number of worker processes to
run; a starting value could be ``CPU * 2``.

Logs for each request aren't show in the terminal. If an error occurs,
its information is written to the error log file shown when starting the
server.


Binding Externally
------------------

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.

For example, if you created a ``hello`` user and group, you should
install your virtualenv and application as that user, then tell
mod_wsgi to drop to that user after starting.

.. code-block:: text

    $ sudo /home/hello/.venv/bin/mod_wsgi-express start-server \
        /home/hello/wsgi.py \
        --user hello --group hello --port 80 --processes 4

---

## File: docs/deploying/nginx.rst

nginx
=====

`nginx`_ is a fast, production level HTTP server. When serving your
application with one of the WSGI servers listed in :doc:`index`, 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.

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.

.. _nginx: https://nginx.org/


Domain Name
-----------

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 provider's name servers.

To simulate this, you can also edit your ``hosts`` file, located at
``/etc/hosts`` on Linux. Add a line that associates a name with the
local IP.

Modern Linux systems may be configured to treat any domain name that
ends with ``.localhost`` like this without adding it to the ``hosts``
file.

.. code-block:: python
    :caption: ``/etc/hosts``

    127.0.0.1 hello.localhost


Configuration
-------------

The nginx configuration is located at ``/etc/nginx/nginx.conf`` on
Linux. It may be different depending on your operating system. Check the
docs and look for ``nginx.conf``.

Remove or comment out any existing ``server`` section. Add a ``server``
section and use the ``proxy_pass`` directive to point to the address the
WSGI server is listening on. We'll assume the WSGI server is listening
locally at ``http://127.0.0.1:8000``.

.. code-block:: nginx
    :caption: ``/etc/nginx.conf``

    server {
        listen 80;
        server_name _;

        location / {
            proxy_pass http://127.0.0.1:8000/;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Prefix /;
        }
    }

Then :doc:`proxy_fix` so that your application uses these headers.

---

## File: docs/deploying/proxy_fix.rst

Tell Flask it is Behind a Proxy
===============================

When using a reverse proxy, or many Python hosting platforms, the proxy
will intercept and forward all external requests to the local WSGI
server.

From the WSGI server and Flask application's perspectives, requests are
now coming from the HTTP server to the local address, rather than from
the remote address to the external server address.

HTTP servers should set ``X-Forwarded-`` 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
:doc:`werkzeug:middleware/proxy_fix` middleware provided by Werkzeug.

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.

.. code-block:: python

    from werkzeug.middleware.proxy_fix import ProxyFix

    app.wsgi_app = ProxyFix(
        app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1
    )

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.