Документация Python неофициальный перевод

wsgiref.md

419 строк · 51.6 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/2.7/library/wsgiref.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 20.4. [`wsgiref`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref) – утилиты WSGI и эталонная реализация89Новое в версии 2.5.1011Интерфейс шлюза веб-сервера (WSGI) – это стандартный интерфейс между веб-сервером и веб-приложениями на Python. Наличие стандартного интерфейса упрощает использование приложения, поддерживающего WSGI, с различными веб-серверами.1213Только разработчики веб-серверов и фреймворков должны знать все тонкости и пограничные случаи дизайна WSGI. Чтобы установить WSGI-приложение или написать веб-приложение с помощью готового фреймворка, не нужно понимать каждую деталь WSGI.1415[`wsgiref`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref) – эталонная реализация спецификации WSGI, которую можно использовать для добавления поддержки WSGI в веб-сервер или фреймворк. Она предоставляет утилиты для работы с переменными окружения WSGI и заголовками ответов, базовые классы для реализации WSGI-серверов, демонстрационный HTTP-сервер, обслуживающий WSGI-приложения, и инструмент проверки, который проверяет соответствие WSGI-серверов и приложений спецификации WSGI ([**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html)).1617См. [https://wsgi.readthedocs.org/](https://python-all.ru/2.7/library/wsgiref.html) для получения дополнительной информации о WSGI, а также ссылки на руководства и другие ресурсы.1819## 20.4.1. [`wsgiref.util`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.util) – утилиты окружения WSGI2021Этот модуль предоставляет различные вспомогательные функции для работы с окружениями WSGI. Окружение WSGI – это словарь, содержащий переменные HTTP-запроса, как описано в [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html). Все функции, принимающие параметр *environ*, ожидают словарь, совместимый с WSGI; подробную спецификацию см. в [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html).2223#### `wsgiref.util.guess_scheme(environ)`2425Возвращает предположение о том, должно ли `wsgi.url_scheme` быть "http" или "https", проверяя переменную окружения `HTTPS` в словаре *environ*. Возвращаемое значение – строка.2627Эта функция полезна при создании шлюза, который оборачивает CGI или протокол, подобный CGI, такой как FastCGI. Обычно серверы, предоставляющие такие протоколы, включают переменную `HTTPS` со значением «1», «yes» или «on», когда запрос получен через SSL. Таким образом, эта функция возвращает «https», если такое значение найдено, и «http» в противном случае.2829#### `wsgiref.util.request_uri(environ, include_query=1)`3031Возвращает полный URI запроса, опционально включая строку запроса, используя алгоритм из раздела «URL Reconstruction» [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html). Если *include\_query* равен false, строка запроса не включается в результирующий URI.3233#### `wsgiref.util.application_uri(environ)`3435Аналогично [`request_uri()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.util.request_uri), за исключением того, что переменные `PATH_INFO` и `QUERY_STRING` игнорируются. Результат – базовый URI объекта приложения, адресованного запросом.3637#### `wsgiref.util.shift_path_info(environ)`3839Перемещает одно имя из `PATH_INFO` в `SCRIPT_NAME` и возвращает это имя. Словарь *environ* изменяется *на месте*; используйте копию, если нужно сохранить исходные `PATH_INFO` или `SCRIPT_NAME` неизменными.4041Если в `PATH_INFO` не осталось сегментов пути, возвращается `None`.4243Обычно эта процедура используется для обработки каждой части пути URI запроса, например, чтобы рассматривать путь как последовательность ключей словаря. Эта процедура изменяет переданное окружение, чтобы сделать его пригодным для вызова другого WSGI-приложения, расположенного по целевому URI. Например, если есть WSGI-приложение по адресу `/foo`, и путь URI запроса – `/foo/bar/baz`, и WSGI-приложение по адресу `/foo` вызывает [`shift_path_info()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.util.shift_path_info), оно получит строку “bar”, а окружение будет обновлено для передачи WSGI-приложению по адресу `/foo/bar`. То есть, `SCRIPT_NAME` изменится с `/foo` на `/foo/bar`, а `PATH_INFO` изменится с `/bar/baz` на `/baz`.4445Когда `PATH_INFO` представляет собой просто “/”, эта процедура возвращает пустую строку и добавляет завершающий слеш к `SCRIPT_NAME`, хотя пустые сегменты пути обычно игнорируются, и `SCRIPT_NAME` обычно не заканчивается слешем. Это преднамеренное поведение, чтобы гарантировать, что приложение сможет отличить URI, заканчивающиеся на `/x`, от URI, заканчивающихся на `/x/`, при использовании этой процедуры для обхода объектов.4647#### `wsgiref.util.setup_testing_defaults(environ)`4849Обновляет *environ* простыми значениями по умолчанию для целей тестирования.5051Эта подпрограмма добавляет различные параметры, необходимые для WSGI, включая `HTTP_HOST`, `SERVER_NAME`, `SERVER_PORT`, `REQUEST_METHOD`, `SCRIPT_NAME`, `PATH_INFO` и все переменные `wsgi.*`, определённые в [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html). Она предоставляет только значения по умолчанию и не заменяет существующие настройки этих переменных.5253Эта процедура предназначена для упрощения настройки фиктивных окружений в модульных тестах серверов и приложений WSGI. Её НЕ следует использовать в реальных серверах или приложениях WSGI, поскольку данные являются фиктивными!5455Пример использования:5657```python58from wsgiref.util import setup_testing_defaults59from wsgiref.simple_server import make_server6061# Относительно простое WSGI-приложение. Оно выведет62# словарь окружения после обновления с помощью setup_testing_defaults63def simple_app(environ, start_response):64    setup_testing_defaults(environ)6566    status = '200 OK'67    headers = [('Content-type', 'text/plain')]6869    start_response(status, headers)7071    ret = ["%s: %s\n" % (key, value)72           for key, value in environ.iteritems()]73    return ret7475httpd = make_server('', 8000, simple_app)76print "Serving on port 8000..."77httpd.serve_forever()78```7980В дополнение к функциям окружения, описанным выше, модуль [`wsgiref.util`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.util) также предоставляет следующие вспомогательные утилиты:8182#### `wsgiref.util.is_hop_by_hop(header_name)`8384Возвращает true, если ‘header\_name’ является HTTP/1.1 “Hop-by-Hop” заголовком, как определено в [**RFC 2616**](https://python-all.ru/2.7/library/wsgiref.html).8586#### `class wsgiref.util.FileWrapper(filelike, blksize=8192)`8788Обёртка для преобразования файлоподобного объекта в [итератор](https://python-all.ru/2.7/glossary.html#term-iterator). Полученные объекты поддерживают оба стиля итерации [`__getitem__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__getitem__) и [`__iter__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__iter__) для совместимости с Python 2.1 и Jython. При итерации по объекту необязательный параметр *blksize* будет многократно передаваться методу `read()` объекта *filelike* для получения строк для возврата. Когда `read()` возвращает пустую строку, итерация завершается и не может быть возобновлена.8990Если *файлоподобный объект* имеет метод `close()`, возвращаемый объект также будет иметь метод `close()`, и при вызове он будет вызывать метод `close()` объекта *файлоподобный объект*.9192Пример использования:9394```python95from StringIO import StringIO96from wsgiref.util import FileWrapper9798# В качестве файлоподобного объекта используется буфер StringIO99filelike = StringIO("This is an example file-like object"*10)100wrapper = FileWrapper(filelike, blksize=5)101102for chunk in wrapper:103    print chunk104```105106## 20.4.2. [`wsgiref.headers`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.headers) – инструменты для заголовков ответа WSGI107108Этот модуль предоставляет единственный класс [`Headers`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.headers.Headers) для удобной работы с заголовками ответов WSGI через интерфейс, напоминающий словарь (mapping).109110#### `class wsgiref.headers.Headers(headers)`111112Создаёт объект, подобный отображению, оборачивающий *headers*, который должен быть списком кортежей «имя заголовка/значение», как описано в [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html). Любые изменения в новом объекте [`Headers`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.headers.Headers) будут напрямую обновлять список *headers*, с которым он был создан.113114Объекты [`Headers`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.headers.Headers) поддерживают типичные операции отображения, включая [`__getitem__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__getitem__), `get()`, [`__setitem__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__setitem__), `setdefault()`, [`__delitem__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__delitem__), [`__contains__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__contains__) и `has_key()`. Для каждого из этих методов ключом является имя заголовка (регистронезависимо), а значением – первое значение, связанное с этим именем заголовка. Установка заголовка удаляет все существующие значения для этого заголовка, а затем добавляет новое значение в конец обёрнутого списка заголовков. Существующий порядок заголовков в целом сохраняется, новые заголовки добавляются в конец обёрнутого списка.115116В отличие от словаря, объекты [`Headers`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.headers.Headers) не вызывают ошибку при попытке получить или удалить ключ, которого нет в обёрнутом списке заголовков. Получение несуществующего заголовка просто возвращает `None`, а удаление несуществующего заголовка ничего не делает.117118Объекты [`Headers`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.headers.Headers) также поддерживают методы `keys()`, `values()` и `items()`. Списки, возвращаемые `keys()` и `items()`, могут содержать один и тот же ключ несколько раз, если заголовок многозначный. Длина (`len()`) объекта [`Headers`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.headers.Headers) равна длине его `items()`, которая равна длине обёрнутого списка заголовков. По сути, метод `items()` просто возвращает копию обёрнутого списка заголовков.119120Вызов `str()` на объекте [`Headers`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.headers.Headers) возвращает отформатированную строку, пригодную для передачи в качестве заголовков HTTP-ответа. Каждый заголовок помещается на отдельной строке с его значением, разделённых двоеточием и пробелом. Каждая строка завершается символами возврата каретки и перевода строки, а вся строка завершается пустой строкой.121122В дополнение к интерфейсу отображения и функциям форматирования, объекты [`Headers`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.headers.Headers) также имеют следующие методы для запроса и добавления многозначных заголовков, а также для добавления заголовков с MIME-параметрами:123124#### `get_all(name)`125126Возвращает список всех значений для указанного заголовка.127128Возвращаемый список будет отсортирован в порядке появления в исходном списке заголовков или добавления в данный экземпляр, и может содержать дубликаты. Любые удалённые и повторно вставленные поля всегда добавляются в конец списка заголовков. Если полей с указанным именем не существует, возвращается пустой список.129130#### `add_header(name, value, **_params)`131132Добавляет (возможно, многозначный) заголовок с необязательными MIME-параметрами, задаваемыми через именованные аргументы.133134*name* – это добавляемое поле заголовка. Именованные аргументы можно использовать для установки MIME-параметров поля заголовка. Каждый параметр должен быть строкой или `None`. Подчёркивания в именах параметров заменяются на дефисы, поскольку дефисы недопустимы в идентификаторах Python, но многие имена MIME-параметров содержат дефисы. Если значение параметра – строка, оно добавляется к параметрам значения заголовка в виде `name="value"`. Если это `None`, добавляется только имя параметра. (Это используется для MIME-параметров без значения.) Пример использования:135136```python137h.add_header('content-disposition', 'attachment', filename='bud.gif')138```139140Приведённый выше код добавит заголовок, который будет выглядеть так:141142```python143Content-Disposition: attachment; filename="bud.gif"144```145146## 20.4.3. [`wsgiref.simple_server`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.simple_server) – простой HTTP-сервер WSGI147148Этот модуль реализует простой HTTP-сервер (на базе [`BaseHTTPServer`](https://python-all.ru/2.7/library/basehttpserver.html#module-BaseHTTPServer)), обслуживающий WSGI-приложения. Каждый экземпляр сервера обслуживает одно WSGI-приложение на заданном хосте и порту. Если требуется обслуживать несколько приложений на одном хосте и порту, следует создать WSGI-приложение, которое анализирует `PATH_INFO`, чтобы выбрать, какое приложение вызывать для каждого запроса. (Например, с помощью функции `shift_path_info()` из [`wsgiref.util`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.util).)149150#### `wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler)`151152Создаёт новый WSGI-сервер, прослушивающий *host* и *port*, принимающий соединения для *app*. Возвращаемое значение – экземпляр переданного *server\_class*, который будет обрабатывать запросы с использованием указанного *handler\_class*. *app* должен быть объектом WSGI-приложения, как определено в [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html).153154Пример использования:155156```python157from wsgiref.simple_server import make_server, demo_app158159httpd = make_server('', 8000, demo_app)160print "Serving HTTP on port 8000..."161162# Отвечать на запросы до завершения процесса163httpd.serve_forever()164165# Альтернатива: обработать один запрос и завершить работу166httpd.handle_request()167```168169#### `wsgiref.simple_server.demo_app(environ, start_response)`170171Эта функция представляет собой небольшое, но полноценное WSGI-приложение, которое возвращает текстовую страницу с сообщением «Hello world!» и списком пар ключ/значение, переданных в параметре *environ*. Она полезна для проверки того, что WSGI-сервер (например, [`wsgiref.simple_server`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.simple_server)) способен корректно запустить простое WSGI-приложение.172173#### `class wsgiref.simple_server.WSGIServer(server_address, RequestHandlerClass)`174175Создаёт экземпляр [`WSGIServer`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.WSGIServer). *server\_address* должен быть кортежем `(host,port)`, а *RequestHandlerClass* – подклассом [`BaseHTTPServer.BaseHTTPRequestHandler`](https://python-all.ru/2.7/library/basehttpserver.html#BaseHTTPServer.BaseHTTPRequestHandler), который будет использоваться для обработки запросов.176177Обычно нет необходимости вызывать этот конструктор, поскольку функция [`make_server()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.make_server) берёт на себя все детали.178179[`WSGIServer`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.WSGIServer) является подклассом [`BaseHTTPServer.HTTPServer`](https://python-all.ru/2.7/library/basehttpserver.html#BaseHTTPServer.HTTPServer), поэтому все его методы (такие как `serve_forever()` и `handle_request()`) доступны. [`WSGIServer`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.WSGIServer) также предоставляет следующие специфичные для WSGI методы:180181#### `set_app(application)`182183Устанавливает вызываемый объект *application* в качестве WSGI-приложения, которое будет получать запросы.184185#### `get_app()`186187Возвращает установленный в данный момент вызываемый объект приложения.188189Однако обычно нет необходимости использовать эти дополнительные методы, так как [`set_app()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.WSGIServer.set_app) обычно вызывается [`make_server()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.make_server), а [`get_app()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.WSGIServer.get_app) существует в основном для удобства экземпляров обработчиков запросов.190191#### `class wsgiref.simple_server.WSGIRequestHandler(request, client_address, server)`192193Создаёт HTTP-обработчик для заданного *request* (т.е. сокета), *client\_address* (кортеж `(host,port)`) и *server* (экземпляр [`WSGIServer`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.WSGIServer)).194195Нет необходимости создавать экземпляры этого класса напрямую; они создаются автоматически по мере необходимости объектами [`WSGIServer`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.WSGIServer). Однако можно создать подкласс этого класса и передать его в качестве *handler\_class* функции [`make_server()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.make_server). Некоторые методы, которые могут быть переопределены в подклассах:196197#### `get_environ()`198199Возвращает словарь, содержащий окружение WSGI для запроса. Реализация по умолчанию копирует содержимое атрибута-словаря `base_environ` объекта [`WSGIServer`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.simple_server.WSGIServer), а затем добавляет различные заголовки, полученные из HTTP-запроса. Каждый вызов этого метода должен возвращать новый словарь, содержащий все соответствующие переменные окружения CGI, как указано в [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html).200201#### `get_stderr()`202203Возвращает объект, который следует использовать в качестве потока `wsgi.errors`. Реализация по умолчанию просто возвращает `sys.stderr`.204205#### `handle()`206207Обрабатывает HTTP-запрос. Реализация по умолчанию создаёт экземпляр обработчика, используя класс [`wsgiref.handlers`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.handlers) для реализации фактического интерфейса WSGI-приложения.208209## 20.4.4. [`wsgiref.validate`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.validate) – проверка соответствия WSGI210211При создании новых объектов WSGI-приложений, фреймворков, серверов или промежуточного ПО может быть полезно проверить соответствие нового кода с помощью [`wsgiref.validate`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.validate). Этот модуль предоставляет функцию, которая создаёт объекты WSGI-приложений, проверяющие взаимодействие между WSGI-сервером или шлюзом и объектом WSGI-приложения, чтобы проверить обе стороны на соответствие протоколу.212213Обратите внимание, что эта утилита не гарантирует полного соответствия [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html); отсутствие ошибок от этого модуля не обязательно означает, что ошибок нет. Однако если этот модуль выдаёт ошибку, то практически наверняка либо сервер, либо приложение не соответствует требованиям на 100%.214215Этот модуль основан на модуле `paste.lint` из библиотеки «Python Paste» Иана Бикинга.216217#### `wsgiref.validate.validator(application)`218219Обёртывает *application* и возвращает новый объект WSGI-приложения. Возвращённое приложение будет перенаправлять все запросы исходному *application* и будет проверять, что и *application*, и вызывающий его сервер соответствуют спецификации WSGI и RFC 2616.220221Любое обнаруженное несоответствие приводит к возбуждению [`AssertionError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.AssertionError); однако обратите внимание, что обработка этих ошибок зависит от сервера. Например, [`wsgiref.simple_server`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.simple_server) и другие серверы на основе [`wsgiref.handlers`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.handlers) (которые не переопределяют методы обработки ошибок для других действий) просто выведут сообщение о том, что произошла ошибка, и отправят трассировку в `sys.stderr` или другой поток ошибок.222223Эта обёртка также может генерировать вывод с помощью модуля [`warnings`](https://python-all.ru/2.7/library/warnings.html#module-warnings) для указания на сомнительное поведение, которое может не быть явно запрещено спецификацией [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html). Если такие предупреждения не подавлены с помощью параметров командной строки Python или API [`warnings`](https://python-all.ru/2.7/library/warnings.html#module-warnings), они будут записаны в `sys.stderr` (*но не* в `wsgi.errors`, если только эти объекты не совпадают).224225Пример использования:226227```python228from wsgiref.validate import validator229from wsgiref.simple_server import make_server230231# Наш вызываемый объект, который намеренно не соответствует232# стандарту, поэтому валидатор выдаст ошибку233def simple_app(environ, start_response):234    status = '200 OK'  # HTTP-статус235    headers = [('Content-type', 'text/plain')]  # HTTP-заголовки236    start_response(status, headers)237238    # Это приведёт к ошибке, потому что нужно вернуть список, и239    # валидатор сообщит об этом240    return "Hello World"241242# Это приложение, обёрнутое в валидатор243validator_app = validator(simple_app)244245httpd = make_server('', 8000, validator_app)246print "Listening on port 8000...."247httpd.serve_forever()248```249250## 20.4.5. [`wsgiref.handlers`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.handlers) – базовые классы сервера/шлюза251252Этот модуль предоставляет базовые классы обработчиков для реализации WSGI-серверов и шлюзов. Эти базовые классы берут на себя большую часть работы по взаимодействию с WSGI-приложением при условии, что им предоставлено окружение, подобное CGI, а также потоки ввода, вывода и ошибок.253254#### `class wsgiref.handlers.CGIHandler`255256Вызов на основе CGI через `sys.stdin`, `sys.stdout`, `sys.stderr` и `os.environ`. Это полезно, когда есть WSGI-приложение, которое нужно запустить как CGI-скрипт. Просто вызовите `CGIHandler().run(app)`, где `app` – это объект WSGI-приложения, которое требуется вызвать.257258Этот класс является подклассом [`BaseCGIHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler), который устанавливает `wsgi.run_once` в true, `wsgi.multithread` в false, а `wsgi.multiprocess` в true и всегда использует [`sys`](https://python-all.ru/2.7/library/sys.html#module-sys) и [`os`](https://python-all.ru/2.7/library/os.html#module-os) для получения необходимых CGI-потоков и окружения.259260#### `class wsgiref.handlers.BaseCGIHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)`261262Аналогично [`CGIHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.CGIHandler), но вместо использования модулей [`sys`](https://python-all.ru/2.7/library/sys.html#module-sys) и [`os`](https://python-all.ru/2.7/library/os.html#module-os) окружение CGI и потоки ввода-вывода задаются явно. Значения *multithread* и *multiprocess* используются для установки флагов `wsgi.multithread` и `wsgi.multiprocess` для любых приложений, запускаемых экземпляром обработчика.263264Этот класс является подклассом [`SimpleHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.SimpleHandler), предназначенным для использования с программами, отличными от HTTP-«исходных серверов». Если вы пишете реализацию шлюзового протокола (например, CGI, FastCGI, SCGI и т.д.), которая использует заголовок `Status:` для отправки HTTP-статуса, то, вероятно, стоит создать подкласс этого класса, а не [`SimpleHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.SimpleHandler).265266#### `class wsgiref.handlers.SimpleHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)`267268Похож на [`BaseCGIHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler), но предназначен для использования с исходными HTTP-серверами. Если вы пишете реализацию HTTP-сервера, то, вероятно, стоит создать подкласс этого класса, а не [`BaseCGIHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler).269270Этот класс является подклассом [`BaseHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler). Он переопределяет методы [`__init__()`](https://python-all.ru/2.7/reference/datamodel.html#object.__init__), `get_stdin()`, `get_stderr()`, `add_cgi_vars()`, `_write()` и `_flush()` для поддержки явной установки окружения и потоков через конструктор. Предоставленные окружение и потоки сохраняются в атрибутах `stdin`, `stdout`, `stderr` и `environ`.271272#### `class wsgiref.handlers.BaseHandler`273274Это абстрактный базовый класс для запуска WSGI-приложений. Каждый экземпляр будет обрабатывать один HTTP-запрос, хотя в принципе можно создать подкласс, пригодный для повторного использования для нескольких запросов.275276Экземпляры [`BaseHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler) имеют только один метод, предназначенный для внешнего использования:277278#### `run(app)`279280Запускает указанное WSGI-приложение *app*.281282Все остальные методы [`BaseHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler) вызываются этим методом в процессе выполнения приложения и, по существу, существуют для возможности настройки процесса.283284Следующие методы ОБЯЗАТЕЛЬНО должны быть переопределены в подклассе:285286#### `_write(data)`287288Буферизует строку *data* для передачи клиенту. Ничего страшного, если этот метод фактически передаёт данные; [`BaseHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler) просто разделяет операции записи и сброса для повышения эффективности, когда базовая система действительно имеет такое различие.289290#### `_flush()`291292Принудительно отправляет буферизованные данные клиенту. Нормально, если этот метод ничего не делает (т.е. если [`_write()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler._write) фактически отправляет данные).293294#### `get_stdin()`295296Возвращает объект входного потока, подходящий для использования в качестве `wsgi.input` текущего обрабатываемого запроса.297298#### `get_stderr()`299300Возвращает объект выходного потока, подходящий для использования в качестве `wsgi.errors` текущего обрабатываемого запроса.301302#### `add_cgi_vars()`303304Вставляет переменные CGI для текущего запроса в атрибут `environ`.305306Вот некоторые другие методы и атрибуты, которые вы можете захотеть переопределить. Однако этот список является лишь кратким обзором и не включает все методы, которые можно переопределить. Перед попыткой создать собственный подкласс [`BaseHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler) следует ознакомиться с дополнительной информацией в строках документации и исходном коде.307308Атрибуты и методы для настройки окружения WSGI:309310#### `wsgi_multithread`311312Значение, которое будет использоваться для переменной окружения `wsgi.multithread`. По умолчанию оно равно true в [`BaseHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler), но может иметь другое значение по умолчанию (или быть установлено конструктором) в других подклассах.313314#### `wsgi_multiprocess`315316Значение, которое будет использоваться для переменной окружения `wsgi.multiprocess`. По умолчанию оно равно true в [`BaseHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler), но может иметь другое значение по умолчанию (или быть установлено конструктором) в других подклассах.317318#### `wsgi_run_once`319320Значение, которое будет использоваться для переменной окружения `wsgi.run_once`. По умолчанию оно равно false в [`BaseHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler), но [`CGIHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.CGIHandler) устанавливает его в true по умолчанию.321322#### `os_environ`323324Переменные окружения по умолчанию, которые будут включены в WSGI-окружение каждого запроса. По умолчанию это копия `os.environ` на момент импорта [`wsgiref.handlers`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.handlers), но подклассы могут создать собственные на уровне класса или экземпляра. Обратите внимание, что словарь следует считать доступным только для чтения, поскольку значение по умолчанию совместно используется несколькими классами и экземплярами.325326#### `server_software`327328Если атрибут [`origin_server`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server) установлен, его значение используется для установки переменной окружения WSGI `SERVER_SOFTWARE` по умолчанию, а также для установки заголовка `Server:` по умолчанию в HTTP-ответах. Он игнорируется для обработчиков (таких как [`BaseCGIHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler) и [`CGIHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.CGIHandler)), которые не являются исходными HTTP-серверами.329330#### `get_scheme()`331332Возвращает схему URL, используемую для текущего запроса. Реализация по умолчанию использует функцию `guess_scheme()` из [`wsgiref.util`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.util), чтобы определить, должна ли схема быть «http» или «https», на основе переменных `environ` текущего запроса.333334#### `setup_environ()`335336Устанавливает атрибут `environ` в полностью заполненное WSGI-окружение. Реализация по умолчанию использует все перечисленные выше методы и атрибуты, а также [`get_stdin()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stdin), [`get_stderr()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stderr) и [`add_cgi_vars()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.add_cgi_vars) методы и атрибут [`wsgi_file_wrapper`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.wsgi_file_wrapper). Она также вставляет ключ `SERVER_SOFTWARE`, если он отсутствует, при условии, что атрибут [`origin_server`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server) имеет истинное значение, а атрибут [`server_software`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.server_software) установлен.337338Методы и атрибуты для настройки обработки исключений:339340#### `log_exception(exc_info)`341342Записывает кортеж *exc\_info* в журнал сервера. *exc\_info* – это кортеж `(type, value, traceback)`. Реализация по умолчанию просто записывает трассировку в поток `wsgi.errors` запроса и сбрасывает его. Подклассы могут переопределить этот метод, чтобы изменить формат или перенаправить вывод, отправить трассировку администратору по почте или выполнить любое другое действие, которое сочтут подходящим.343344#### `traceback_limit`345346Максимальное количество фреймов, включаемых в трассировки, выводимые методом [`log_exception()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.log_exception) по умолчанию. Если `None`, включаются все фреймы.347348#### `error_output(environ, start_response)`349350Этот метод представляет собой WSGI-приложение для генерации страницы ошибки для пользователя. Он вызывается только в том случае, если ошибка возникает до отправки заголовков клиенту.351352Этот метод может получить текущую информацию об ошибке с помощью `sys.exc_info()` и должен передать эту информацию в *start\_response* при его вызове (как описано в разделе «Обработка ошибок» [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html)).353354Реализация по умолчанию просто использует атрибуты [`error_status`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_status), [`error_headers`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_headers) и [`error_body`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_body) для генерации выходной страницы. Подклассы могут переопределить это для создания более динамичного вывода ошибок.355356Однако с точки зрения безопасности не рекомендуется выводить диагностическую информацию любому пользователю; в идеале необходимо выполнить специальные действия для включения диагностического вывода, поэтому в реализации по умолчанию он отсутствует.357358#### `error_status`359360HTTP-статус, используемый для ответов об ошибках. Это должна быть строка статуса, как определено в [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html); по умолчанию используется код 500 и соответствующее сообщение.361362#### `error_headers`363364Заголовки HTTP, используемые для ответов об ошибках. Это должен быть список заголовков ответа WSGI (кортежи `(name, value)`), как описано в [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html). Список по умолчанию просто устанавливает тип содержимого в `text/plain`.365366#### `error_body`367368Тело ответа об ошибке. Это должна быть строка тела HTTP-ответа. По умолчанию используется обычный текст: «Произошла ошибка сервера. Пожалуйста, свяжитесь с администратором».369370Методы и атрибуты для [**PEP 333**](https://python-all.ru/2.7/library/wsgiref.html), реализующие возможность «Опциональная обработка файлов на уровне платформы»:371372#### `wsgi_file_wrapper`373374Фабрика `wsgi.file_wrapper`, или `None`. Значение по умолчанию этого атрибута – класс `FileWrapper` из [`wsgiref.util`](https://python-all.ru/2.7/library/wsgiref.html#module-wsgiref.util).375376#### `sendfile()`377378Переопределите для реализации передачи файлов, зависящей от платформы. Этот метод вызывается только в том случае, если возвращаемое значение приложения является экземпляром класса, указанного атрибутом [`wsgi_file_wrapper`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.wsgi_file_wrapper). Он должен возвращать истинное значение, если файл был успешно передан, чтобы код передачи по умолчанию не выполнялся. Реализация этого метода по умолчанию просто возвращает ложное значение.379380Разные методы и атрибуты:381382#### `origin_server`383384Этот атрибут должен быть установлен в истинное значение, если [`_write()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler._write) и [`_flush()`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler._flush) обработчика используются для прямой связи с клиентом, а не через шлюзовой протокол типа CGI, который ожидает HTTP-статус в специальном заголовке `Status:`.385386Значение этого атрибута по умолчанию равно true в [`BaseHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler), но false в [`BaseCGIHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler) и [`CGIHandler`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.CGIHandler).387388#### `http_version`389390Если [`origin_server`](https://python-all.ru/2.7/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server) равно True, этот строковый атрибут используется для установки HTTP-версии ответа, отправляемого клиенту. По умолчанию он равен `"1.0"`.391392## 20.4.6. Примеры393394Это рабочее WSGI-приложение «Hello World»:395396```python397from wsgiref.simple_server import make_server398399# Каждое WSGI-приложение должно иметь объект приложения – вызываемый400# объект, который принимает два аргумента. Для этого401# можно использовать функцию (обратите внимание: можно не только функцию, но и, например, класс)402# использовать, например, класс). Первый аргумент, передаваемый функции,403# это словарь, содержащий переменные окружения в стиле CGI, а404# вторая переменная – это вызываемый объект (см. PEP 333).405def hello_world_app(environ, start_response):406    status = '200 OK'  # HTTP-статус407    headers = [('Content-type', 'text/plain')]  # HTTP-заголовки408    start_response(status, headers)409410    # Возвращаемый объект будет выведен411    return ["Hello World"]412413httpd = make_server('', 8000, hello_world_app)414print "Serving on port 8000..."415416# Обслуживать до завершения процесса417httpd.serve_forever()418```419