• en
  • Language: ru
  • Documentation version: 1.1.x

Автономные контейнеры WSGI

Существуют популярные серверы, написанные на Python, которые содержат приложения WSGI и обслуживают HTTP. Эти серверы работают отдельно; вы можете обращаться к ним через прокси-сервер с вашего веб-сервера. Обратите внимание на раздел Настройки прокси-сервера, если у вас возникнут проблемы.

Gunicorn

<

$ gunicorn myproject:app

Gunicorn предоставляет множество опций командной строки - смотрите gunicorn -h. Например, для запуска приложения Flask с 4 рабочими процессами (-w 4), связывающимися с портом localhost 4000 (-b 127.0.0.1:4000):

$ gunicorn -w 4 -b 127.0.0.1:4000 myproject:app

Команда gunicorn ожидает имена модуля или пакета вашего приложения и экземпляра приложения в модуле. Если вы используете шаблон фабрики приложений, вы можете передать вызов:

$ gunicorn "myproject:create_app()"

uWSGI

uWSGI - это быстрый сервер приложений, написанный на языке C. Он очень настраиваемый, что делает его более сложным в настройке, чем gunicorn.

Выполняется uWSGI HTTP Router:

$ uwsgi --http 127.0.0.1:5000 --module myproject:app

Для более оптимизированной настройки смотрите configuring uWSGI and NGINX.

Gevent

Gevent - это сетевая библиотека Python на основе корутин, которая использует greenlet для обеспечения высокоуровневого синхронного API поверх цикла событий libev:

from gevent.pywsgi import WSGIServer
from yourapplication import app

http_server = WSGIServer(('', 5000), app)
http_server.serve_forever()

Крученая паутина

Twisted Web - это веб-сервер, поставляемый с Twisted, зрелой, неблокирующей событийно-управляемой сетевой библиотекой. Twisted Web поставляется со стандартным контейнером WSGI, которым можно управлять из командной строки с помощью утилиты twistd:

$ twistd web --wsgi myproject.app

В этом примере будет запущено приложение Flask под названием app из модуля под названием myproject.

Twisted Web поддерживает множество флагов и опций, и утилита twistd также поддерживает их; более подробная информация приведена в разделах twistd -h и twistd web -h. Например, чтобы запустить сервер Twisted Web на переднем плане, на порту 8080, с приложением из myproject:

$ twistd -n web --port tcp:8080 --wsgi myproject.app

Настройки прокси-сервера

Если вы развертываете свое приложение, используя один из этих серверов за HTTP-прокси, вам придется переписать несколько заголовков, чтобы приложение работало. Двумя проблемными значениями в среде WSGI обычно являются REMOTE_ADDR и HTTP_HOST. Вы можете настроить httpd на передачу этих заголовков или исправить их в промежуточном ПО. Werkzeug поставляет программу исправления, которая решает некоторые распространенные проблемы, но вы можете захотеть написать собственное промежуточное ПО WSGI для конкретных ситуаций.

Вот простая конфигурация nginx, которая проксирует приложение, обслуживаемое на localhost на порту 8000, устанавливая соответствующие заголовки:

server {
    listen 80;

    server_name _;

    access_log  /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    location / {
        proxy_pass         http://127.0.0.1:8000/;
        proxy_redirect     off;

        proxy_set_header   Host                 $host;
        proxy_set_header   X-Real-IP            $remote_addr;
        proxy_set_header   X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto    $scheme;
    }
}

Если ваш httpd не предоставляет эти заголовки, наиболее распространенная настройка предполагает установку хоста из X-Forwarded-Host и удаленного адреса из X-Forwarded-For:

from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)

Доверие к заголовкам

Пожалуйста, имейте в виду, что использование такого промежуточного ПО в непрокси-установке является проблемой безопасности, поскольку оно будет слепо доверять входящим заголовкам, которые могут быть подделаны вредоносными клиентами.

Если вы хотите переписать заголовки из другого заголовка, вы можете использовать исправляющее устройство, например, такое:

class CustomProxyFix(object):

    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        host = environ.get('HTTP_X_FHOST', '')
        if host:
            environ['HTTP_HOST'] = host
        return self.app(environ, start_response)

app.wsgi_app = CustomProxyFix(app.wsgi_app)