Введение в Werkzeug и WSGI

задняя часть Python сервер Flask

WerkzeugЭто набор инструментов WSGI, который также можно использовать в качестве базовой библиотеки для веб-фреймворка.

WSGI


Прежде чем представить Werkzeug, давайте сначала представим WSGI (интерфейс шлюза веб-сервера Python), который представляет собой простой и распространенный интерфейс между веб-сервером и веб-приложением или инфраструктурой, определяемой языком Python. Это спецификация, которая описывает, как веб-сервер взаимодействует с веб-приложением и как веб-приложение обрабатывает запросы.PEP3333, настоятельно рекомендуется прочитать PEP3333, прежде чем вернуться к этой статье.

WSGI разделен на две части:

  • Сервер/шлюз: это HTTP-сервер, который отвечает за получение запросов от клиентов (Nginx, apache, IIS), пересылку запросов в приложение и возврат ответа, возвращенного приложением (возможно, приложением Flask) клиенту.
  • Приложение/фреймворк: веб-приложение или веб-фреймворк Python получает запрос, перенаправленный сервером, обрабатывает запрос и возвращает результат обработки на сервер.

Следующие два изображения могут быть использованы, чтобы разобраться в вызывающих отношениях между ними:

wsgi server 与 wsgi 应用之间的调用关系

web sever 与 wsgi server 与 web browser之间的调用流程

Сначала поймите из примера кода:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['Hello World!']

Самое простое приложение WSGI, как показано выше, определяет функцию приложения (вызываемый объект), а вызываемый объект (вызываемый объект) включает в себя: функцию, метод, класс или реализацию__call__Экземпляры могут использоваться как объекты приложения. Эта функция принимает два параметра, environ и start_response.

  • environ — это словарь, содержащий переменные окружения в CGI.
  • start_response также является вызываемым, который принимает два обязательных параметра: статус (статус HTTP) и response_headers (заголовок ответного сообщения).

Статус ответа и заголовки ответа возвращаются на сервер через функцию обратного вызова (start_response), а также возвращается тело ответа.Тело ответа повторяемо и содержит несколько строк.

Werkzeug


werkzeug предоставляет функции, связанные с разработкой Python Web WSGI:

  • Обработка маршрутизации: как найти соответствующую функцию просмотра на основе URL-адреса запроса
  • инкапсуляция запросов и ответов: обеспечивает лучший способ обработки запросов и создания объектов ответа
  • Автономный сервер WSGI: тестовая среда, работающая с приложением WSGI

Давайте воспользуемся Werkzeug для реализации простого приложения WSGI:

from werkzeug.wrappers import Request, Response

def application(environ, start_response):
    request = Request(environ)
    text = 'Hello %s!' % request.args.get('name', 'World')
    response = Response(text, mimetype='text/plain')
    return response(environ, start_response)

Как показано в приведенном выше коде, для запроса данных требуется объект среды, и Werkzeug позволяет легко получить доступ к данным. Объект ответа — это приложение WSGI, которое обеспечивает лучший способ создания ответов.

Пожалуйста, обратитесь к документации по созданию приложения WSGI, позже мы упомянем структуру данных Werkzeug, используемую во фреймворке Flask. Вот несколько примеров из официальной документации по созданию веб-приложения с использованием werkzeug:

import os
import redis
import urlparse
from werkzeug.wrappers import Request, Response
from werkzeug.routing import Map, Rule
from werkzeug.exceptions import HTTPException, NotFound
from werkzeug.wsgi import SharedDataMiddleware
from werkzeug.utils import redirect
from jinja2 import Environment, FileSystemLoader

class Shortly(object):
    """ 
    Shortly 是一个实际的 WSGI 应用,通过 __call__ 方法直接调 用 wsgi_app,
    同时通过一个可选设置创建一个中间件,将static文件夹暴露给用户:
    """
    def __init__(self, config):
        self.redis = redis.Redis(config['redis_host'], config['redis_port'])

    def dispatch_request(self, request):
        return Response('Hello World!')

    def wsgi_app(self, environ, start_response):
        request = Request(environ)
        response = self.dispatch_request(request)
        return response(environ, start_response)

    def __call__(self, environ, start_response):
        return self. wsgi_app(environ, start_response)


def create_app(redis_host='localhost', redis_port=6379, with_static=True):
    app = Shortly({
        'redis_host':       redis_host,
        'redis_port':       redis_port
    })
    if with_static:
        app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
            '/static':  os.path.join(os.path.dirname(__file__), 'static')
        })
    return app
    
if __name__ == '__main__':
    from werkzeug.serving import run_simple
    app = create_app()
    run_simple('127.0.0.1', 5000, app, use_debugger=True, use_reloader=True)

Идея проста: Shortly — это настоящее приложение WSGI.__call__метод вызывает wsgi_app напрямую. Сделав это, мы можем украсить промежуточное программное обеспечение вызова wsgi_app так же, как мы это сделали в функции create_app. wsgi_app фактически создает объект Request, затем вызывает объект Request с помощью dispatch_request и возвращает объект Response приложению WSGI. Как видите: либо создается класс Shortly, либо создается объект Werkzeug Request для реализации интерфейса WSGI. Конечным результатом является просто еще одно приложение WSGI, возвращаемое из метода dispatch_request. Эта часть объяснения взята из китайской версии официальной документации.

Суммировать


В этой статье в основном рассказывается о спецификации WSGI и Werkzeug (наборе инструментов WSGI), а также о том, как реализовать приложение WSGI, соответствующее спецификации WSGI Наконец, используя соответствующие модули в наборе инструментов Werkzeug, можно быстро реализовать простое приложение на основе WSGI.

Ссылаться на


Китайская документация Werkzeug

Документация Werkzeug на английском языке

WSGI Servers

Принцип и реализация протокола WSGI