wsgiref.md
1> **Источник:** https://python-all.ru/3.1/library/wsgiref.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 20.4. `wsgiref` – Утилиты WSGI и эталонная реализация89Интерфейс шлюза веб-сервера (WSGI) – это стандартный интерфейс между веб-сервером и веб-приложениями на Python. Наличие стандартного интерфейса упрощает использование приложения, поддерживающего WSGI, с различными веб-серверами.1011Только разработчики веб-серверов и фреймворков должны знать все тонкости и пограничные случаи дизайна WSGI. Чтобы установить WSGI-приложение или написать веб-приложение с помощью готового фреймворка, не нужно понимать каждую деталь WSGI.1213`wsgiref` – эталонная реализация спецификации WSGI, которую можно использовать для добавления поддержки WSGI в веб-сервер или фреймворк. Она предоставляет утилиты для работы с переменными окружения WSGI и заголовками ответов, базовые классы для реализации серверов WSGI, демонстрационный HTTP-сервер, обслуживающий WSGI-приложения, а также инструмент проверки, который контролирует соответствие серверов и приложений спецификации WSGI ([**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html)).1415См. [http://www.wsgi.org](https://python-all.ru/3.1/library/wsgiref.html) для получения дополнительной информации о WSGI, а также ссылки на руководства и другие ресурсы.1617## 20.4.1. `wsgiref.util` – Утилиты окружения WSGI1819Этот модуль предоставляет различные вспомогательные функции для работы с окружениями WSGI. Окружение WSGI – это словарь, содержащий переменные HTTP-запроса, как описано в [**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html). Все функции, принимающие параметр *environ*, ожидают словарь, совместимый с WSGI; подробную спецификацию см. в [**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html).2021#### `wsgiref.util.guess_scheme(environ)`2223Возвращает предположение о том, должно ли `wsgi.url_scheme` быть «http» или «https», проверяя наличие переменной окружения `HTTPS` в словаре *environ*. Возвращаемое значение – строка.2425Эта функция полезна при создании шлюза, который оборачивает CGI или протокол, подобный CGI, например FastCGI. Обычно серверы, реализующие такие протоколы, включают переменную `HTTPS` со значением «1», «yes» или «on», когда запрос получен по SSL. Поэтому функция возвращает «https», если такое значение найдено, и «http» в противном случае.2627#### `wsgiref.util.request_uri(environ, include_query=True)`2829Возвращает полный URI запроса, опционально включая строку запроса, используя алгоритм из раздела «URL Reconstruction»3031[**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html)3233. Если3435*include\_query*3637равен false, строка запроса не включается в результирующий URI.3839#### `wsgiref.util.application_uri(environ)`4041Похоже на4243[`request_uri()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.util.request_uri)4445, за исключением того, что переменные4647`PATH_INFO`4849и5051`QUERY_STRING`5253игнорируются. Результат – базовый URI объекта приложения, к которому обращается запрос.5455#### `wsgiref.util.shift_path_info(environ)`5657Переносит одно имя из `PATH_INFO` в `SCRIPT_NAME` и возвращает это имя. Словарь *environ* *изменяется* на месте; используйте копию, если нужно сохранить исходные `PATH_INFO` или `SCRIPT_NAME` нетронутыми.5859Если в `PATH_INFO` не осталось сегментов пути, возвращается `None`.6061Обычно эта процедура используется для обработки каждой части пути URI запроса, например, для трактовки пути как последовательности ключей словаря. Эта процедура изменяет переданное окружение, чтобы сделать его подходящим для вызова другого WSGI-приложения, расположенного по целевому URI. Например, если есть WSGI-приложение по адресу `/foo`, а путь URI запроса – `/foo/bar/baz`, и WSGI-приложение по адресу `/foo` вызывает [`shift_path_info()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.util.shift_path_info), то оно получит строку «bar», а окружение будет обновлено для передачи WSGI-приложению по адресу `/foo/bar`. То есть `SCRIPT_NAME` изменится с `/foo` на `/foo/bar`, а `PATH_INFO` изменится с `/bar/baz` на `/baz`.6263Когда `PATH_INFO` содержит просто «/», эта процедура возвращает пустую строку и добавляет завершающий слеш к `SCRIPT_NAME`, хотя пустые сегменты пути обычно игнорируются, а `SCRIPT_NAME` обычно не заканчивается слешем. Это намеренное поведение, чтобы гарантировать, что приложение может отличить URI, оканчивающиеся на `/x`, от оканчивающихся на `/x/` при использовании этой процедуры для обхода объектов.6465#### `wsgiref.util.setup_testing_defaults(environ)`6667Обновляет *environ* простыми значениями по умолчанию для целей тестирования.6869Эта процедура добавляет различные параметры, необходимые для WSGI, включая `HTTP_HOST`, `SERVER_NAME`, `SERVER_PORT`, `REQUEST_METHOD`, `SCRIPT_NAME`, `PATH_INFO`, а также все переменные `wsgi.*`, определённые в [**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html). Она предоставляет только значения по умолчанию и не заменяет существующие настройки этих переменных.7071Эта процедура предназначена для упрощения настройки фиктивных окружений в модульных тестах серверов и приложений WSGI. Её НЕ следует использовать в реальных серверах или приложениях WSGI, поскольку данные являются фиктивными!7273Пример использования:7475```python76from wsgiref.util import setup_testing_defaults77from wsgiref.simple_server import make_server7879# Относительно простое WSGI-приложение. Оно выведет80# словарь окружения после обновления с помощью setup_testing_defaults81def simple_app(environ, start_response):82 setup_testing_defaults(environ)8384 status = b'200 OK'85 headers = [(b'Content-type', b'text/plain; charset=utf-8')]8687 start_response(status, headers)8889 ret = [("%s: %s\n" % (key, value)).encode("utf-8")90 for key, value in environ.items()]91 return ret9293httpd = make_server('', 8000, simple_app)94print("Serving on port 8000...")95httpd.serve_forever()96```9798В дополнение к функциям окружения, описанным выше, модуль `wsgiref.util` также предоставляет следующие прочие утилиты:99100#### `wsgiref.util.is_hop_by_hop(header_name)`101102Возвращает true, если ‘header\_name’ является HTTP/1.1 “Hop-by-Hop” заголовком, как определено в103104[**RFC 2616**](https://python-all.ru/3.1/library/wsgiref.html)105106.107108#### `class wsgiref.util.FileWrapper(filelike, blksize=8192)`109110Обёртка для преобразования файлоподобного объекта в [*итератор*](https://python-all.ru/3.1/glossary.html#term-iterator). Результирующие объекты поддерживают как стиль итерации [`__getitem__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__getitem__), так и [`__iter__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__iter__) для совместимости с Python 2.1 и Jython. При итерации по объекту необязательный параметр *blksize* будет многократно передаваться методу `read()` объекта *filelike* для получения строк, которые возвращаются. Когда `read()` возвращает пустую строку, итерация завершается и не может быть возобновлена.111112Если *filelike* имеет метод `close()`, возвращаемый объект также будет иметь метод `close()`, и при вызове он будет вызывать метод *filelike* `close()`.113114Пример использования:115116```python117from io import StringIO118from wsgiref.util import FileWrapper119120# В качестве файлоподобного объекта используется буфер StringIO121filelike = StringIO("This is an example file-like object"*10)122wrapper = FileWrapper(filelike, blksize=5)123124for chunk in wrapper:125 print(chunk)126```127128## 20.4.2. `wsgiref.headers` – Инструменты для заголовков ответов WSGI129130Этот модуль предоставляет один класс, [`Headers`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.headers.Headers), для удобного управления заголовками ответов WSGI с помощью интерфейса, подобного отображению.131132#### `class wsgiref.headers.Headers(headers)`133134Создаёт объект, подобный отображению, оборачивающий *headers*, который должен быть списком кортежей имя/значение заголовка, как описано в [**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html).135136Объекты [`Headers`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.headers.Headers) поддерживают типичные операции отображения, включая [`__getitem__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__getitem__), `get()`, [`__setitem__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__setitem__), `setdefault()`, [`__delitem__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__delitem__) и [`__contains__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__contains__). Для каждого из этих методов ключом является имя заголовка (регистронезависимое), а значением – первое значение, связанное с этим именем заголовка. Установка заголовка удаляет все существующие значения для этого заголовка, затем добавляет новое значение в конец обёрнутого списка заголовков. Существующий порядок заголовков в целом сохраняется, новые заголовки добавляются в конец обёрнутого списка.137138В отличие от словаря, объекты [`Headers`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.headers.Headers) не вызывают ошибку при попытке получить или удалить ключ, которого нет в обёрнутом списке заголовков. Получение несуществующего заголовка просто возвращает `None`, а удаление несуществующего заголовка ничего не делает.139140Объекты [`Headers`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.headers.Headers) также поддерживают методы `keys()`, `values()` и `items()`. Списки, возвращаемые `keys()` и `items()`, могут включать один и тот же ключ несколько раз, если есть заголовок с несколькими значениями. Длина `len()` объекта [`Headers`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.headers.Headers) равна длине его `items()`, что совпадает с длиной обёрнутого списка заголовков. Фактически, метод `items()` просто возвращает копию обёрнутого списка заголовков.141142Вызов `str()` для объекта [`Headers`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.headers.Headers) возвращает отформатированную строку, пригодную для передачи в качестве заголовков HTTP-ответа. Каждый заголовок помещается на строку со своим значением, разделённые двоеточием и пробелом. Каждая строка завершается возвратом каретки и переводом строки, а вся строка завершается пустой строкой.143144В дополнение к интерфейсу отображения и возможностям форматирования, объекты [`Headers`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.headers.Headers) также имеют следующие методы для запроса и добавления многозначных заголовков, а также для добавления заголовков с MIME-параметрами:145146#### `get_all(name)`147148Возвращает список всех значений для указанного заголовка.149150Возвращаемый список будет отсортирован в порядке появления в исходном списке заголовков или добавления в данный экземпляр, и может содержать дубликаты. Любые удалённые и повторно вставленные поля всегда добавляются в конец списка заголовков. Если полей с указанным именем не существует, возвращается пустой список.151152#### `add_header(name, value, **_params)`153154Добавляет (возможно, многозначный) заголовок с необязательными MIME-параметрами, задаваемыми через именованные аргументы.155156*name* – это добавляемое поле заголовка. Именованные аргументы можно использовать для задания MIME-параметров поля заголовка. Каждый параметр должен быть строкой или `None`. Подчёркивания в именах параметров заменяются на дефисы, так как дефисы недопустимы в идентификаторах Python, но многие имена MIME-параметров содержат дефисы. Если значение параметра – строка, оно добавляется к параметрам значения заголовка в виде `name="value"`. Если это `None`, добавляется только имя параметра. (Используется для MIME-параметров без значения.) Пример использования:157158```python159h.add_header('content-disposition', 'attachment', filename='bud.gif')160```161162Приведённый выше код добавит заголовок, который будет выглядеть так:163164```python165Content-Disposition: attachment; filename="bud.gif"166```167168## 20.4.3. `wsgiref.simple_server` – Простой WSGI HTTP-сервер169170Этот модуль реализует простой HTTP-сервер (на основе [`http.server`](https://python-all.ru/3.1/library/http.server.html#module-http.server)), обслуживающий WSGI-приложения. Каждый экземпляр сервера обслуживает одно WSGI-приложение на заданном хосте и порту. Если требуется обслуживать несколько приложений на одном хосте и порту, следует создать WSGI-приложение, которое анализирует `PATH_INFO` для выбора приложения, вызываемого для каждого запроса. (Например, используя функцию `shift_path_info()` из `wsgiref.util`.)171172#### `wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler)`173174Создаёт новый WSGI-сервер, прослушивающий *host* и *port*, принимающий соединения для *app*. Возвращаемое значение – экземпляр переданного *server\_class*, который будет обрабатывать запросы с использованием указанного *handler\_class*. *app* должен быть объектом WSGI-приложения, как определено в [**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html).175176Пример использования:177178```python179from wsgiref.simple_server import make_server, demo_app180181httpd = make_server('', 8000, demo_app)182print("Serving HTTP on port 8000...")183184# Отвечать на запросы до завершения процесса185httpd.serve_forever()186187# Альтернатива: обработать один запрос и завершить работу188httpd.handle_request()189```190191#### `wsgiref.simple_server.demo_app(environ, start_response)`192193Эта функция представляет собой небольшое, но полноценное WSGI-приложение, возвращающее текстовую страницу с сообщением «Hello world!» и списком пар ключ/значение, переданных в параметре194195*environ*196197. Она полезна для проверки того, что WSGI-сервер (например198199`wsgiref.simple_server`200201) способен корректно запустить простое WSGI-приложение.202203#### `class wsgiref.simple_server.WSGIServer(server_address, RequestHandlerClass)`204205Создаёт экземпляр [`WSGIServer`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.WSGIServer). Параметр *server\_address* должен быть кортежем `(host,port)`, а *RequestHandlerClass* – подклассом [`http.server.BaseHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler), который будет использоваться для обработки запросов.206207Обычно нет необходимости вызывать этот конструктор напрямую, так как функция [`make_server()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.make_server) может обработать все детали за вас.208209[`WSGIServer`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.WSGIServer) является подклассом [`http.server.HTTPServer`](https://python-all.ru/3.1/library/http.server.html#http.server.HTTPServer), поэтому все его методы (такие как `serve_forever()` и `handle_request()`) доступны. [`WSGIServer`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.WSGIServer) также предоставляет следующие WSGI-специфичные методы:210211#### `set_app(application)`212213Устанавливает вызываемый объект214215*application*216217в качестве WSGI-приложения, которое будет получать запросы.218219#### `get_app()`220221Возвращает установленный в данный момент вызываемый объект приложения.222223Однако обычно нет необходимости использовать эти дополнительные методы, так как [`set_app()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.WSGIServer.set_app) обычно вызывается функцией [`make_server()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.make_server), а [`get_app()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.WSGIServer.get_app) существует в основном для удобства экземпляров обработчиков запросов.224225#### `class wsgiref.simple_server.WSGIRequestHandler(request, client_address, server)`226227Создаёт HTTP-обработчик для заданных *request* (т.е. сокета), *client\_address* (кортеж `(host,port)`) и *server* (экземпляр [`WSGIServer`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.WSGIServer)).228229Нет необходимости создавать экземпляры этого класса напрямую; они автоматически создаются по мере необходимости объектами [`WSGIServer`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.WSGIServer). Однако можно создать подкласс этого класса и передать его в качестве *handler\_class* функции [`make_server()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.make_server). Некоторые методы, которые можно переопределить в подклассах:230231#### `get_environ()`232233Возвращает словарь, содержащий окружение WSGI для запроса. Реализация по умолчанию копирует содержимое атрибута-словаря234235`base_environ`236237объекта238239[`WSGIServer`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.simple_server.WSGIServer)240241, а затем добавляет различные заголовки, полученные из HTTP-запроса. Каждый вызов этого метода должен возвращать новый словарь, содержащий все соответствующие переменные окружения CGI, как указано в242243[**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html)244245.246247#### `get_stderr()`248249Возвращает объект, который должен использоваться в качестве потока250251`wsgi.errors`252253. Реализация по умолчанию просто возвращает254255`sys.stderr`256257.258259#### `handle()`260261Обрабатывает HTTP-запрос. Реализация по умолчанию создаёт экземпляр обработчика, используя класс262263`wsgiref.handlers`264265для реализации интерфейса WSGI-приложения.266267## 20.4.4. `wsgiref.validate` – средство проверки соответствия WSGI268269При создании новых объектов WSGI-приложений, фреймворков, серверов или промежуточного ПО может быть полезно проверить соответствие нового кода с помощью `wsgiref.validate`. Этот модуль предоставляет функцию, которая создаёт объекты WSGI-приложений, проверяющие взаимодействие между WSGI-сервером (или шлюзом) и объектом WSGI-приложения, чтобы убедиться в соответствии протоколу с обеих сторон.270271Обратите внимание, что эта утилита не гарантирует полного соответствия [**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html); отсутствие ошибок от этого модуля не обязательно означает, что ошибок нет. Однако если этот модуль выдаёт ошибку, то практически наверняка либо сервер, либо приложение не соответствует требованиям на 100%.272273Этот модуль основан на модуле `paste.lint` из библиотеки Ian Bicking’s «Python Paste».274275#### `wsgiref.validate.validator(application)`276277Обёртывает *application* и возвращает новый объект WSGI-приложения. Возвращённое приложение будет перенаправлять все запросы исходному *application* и будет проверять, что и *application*, и вызывающий его сервер соответствуют спецификации WSGI и RFC 2616.278279Любое обнаруженное несоответствие приводит к возбуждению [`AssertionError`](https://python-all.ru/3.1/library/exceptions.html#AssertionError); при этом способ обработки этих ошибок зависит от сервера. Например, `wsgiref.simple_server` и другие серверы на основе `wsgiref.handlers` (которые не переопределяют методы обработки ошибок для каких-либо других действий) просто выводят сообщение о возникновении ошибки и отправляют трассировку в `sys.stderr` или другой поток ошибок.280281Эта обёртка также может генерировать вывод с помощью модуля [`warnings`](https://python-all.ru/3.1/library/warnings.html#module-warnings) для указания на сомнительное поведение, которое на самом деле может не запрещаться [**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html). Если такие предупреждения не подавлены с помощью параметров командной строки Python или API [`warnings`](https://python-all.ru/3.1/library/warnings.html#module-warnings), они записываются в `sys.stderr` (*не* в `wsgi.errors`, если только они не оказываются одним и тем же объектом).282283Пример использования:284285```python286from wsgiref.validate import validator287from wsgiref.simple_server import make_server288289# Наш вызываемый объект, который намеренно не соответствует290# стандарту, поэтому валидатор выдаст ошибку291def simple_app(environ, start_response):292 status = b'200 OK' # HTTP-статус293 headers = [(b'Content-type', b'text/plain')] # HTTP-заголовки294 start_response(status, headers)295296 # Это приведёт к ошибке, потому что нужно вернуть список, и297 # валидатор сообщит об этом298 return b"Hello World"299300# Это приложение, обёрнутое в валидатор301validator_app = validator(simple_app)302303httpd = make_server('', 8000, validator_app)304print("Listening on port 8000....")305httpd.serve_forever()306```307308## 20.4.5. `wsgiref.handlers` – базовые классы сервера/шлюза309310Этот модуль предоставляет базовые классы обработчиков для реализации WSGI-серверов и шлюзов. Эти базовые классы берут на себя большую часть работы по взаимодействию с WSGI-приложением при условии, что им предоставлено окружение, подобное CGI, а также потоки ввода, вывода и ошибок.311312#### `class wsgiref.handlers.CGIHandler`313314Вызов на основе CGI через `sys.stdin`, `sys.stdout`, `sys.stderr` и `os.environ`. Это полезно, если есть WSGI-приложение, которое нужно запустить как CGI-скрипт. Просто вызовите `CGIHandler().run(app)`, где `app` – объект WSGI-приложения, которое требуется запустить.315316Этот класс является подклассом [`BaseCGIHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler), который устанавливает `wsgi.run_once` в true, `wsgi.multithread` в false и `wsgi.multiprocess` в true, а также всегда использует [`sys`](https://python-all.ru/3.1/library/sys.html#module-sys) и [`os`](https://python-all.ru/3.1/library/os.html#module-os) для получения необходимых CGI-потоков и окружения.317318#### `class wsgiref.handlers.BaseCGIHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)`319320Похож на [`CGIHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.CGIHandler), но вместо использования модулей [`sys`](https://python-all.ru/3.1/library/sys.html#module-sys) и [`os`](https://python-all.ru/3.1/library/os.html#module-os), CGI-окружение и потоки ввода-вывода задаются явно. Значения *multithread* и *multiprocess* используются для установки флагов `wsgi.multithread` и `wsgi.multiprocess` для любых приложений, запускаемых экземпляром обработчика.321322Этот класс является подклассом [`SimpleHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.SimpleHandler), предназначенным для использования с программным обеспечением, отличным от исходных HTTP-серверов. Если вы пишете реализацию шлюзового протокола (такого как CGI, FastCGI, SCGI и т.д.), который использует заголовок `Status:` для отправки HTTP-статуса, вероятно, вам нужно создать подкласс этого класса вместо [`SimpleHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.SimpleHandler).323324#### `class wsgiref.handlers.SimpleHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)`325326Похож на [`BaseCGIHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler), но предназначен для использования с исходными HTTP-серверами. Если разрабатывается реализация HTTP-сервера, вероятно, следует создать подкласс на основе этого, а не [`BaseCGIHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler)327328Этот класс является подклассом [`BaseHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler). Он переопределяет методы [`__init__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__init__), `get_stdin()`, `get_stderr()`, `add_cgi_vars()`, `_write()` и `_flush()`, чтобы поддерживать явное задание окружения и потоков через конструктор. Предоставленные окружение и потоки сохраняются в атрибутах `stdin`, `stdout`, `stderr` и `environ`.329330#### `class wsgiref.handlers.BaseHandler`331332Это абстрактный базовый класс для запуска WSGI-приложений. Каждый экземпляр будет обрабатывать один HTTP-запрос, хотя в принципе можно создать подкласс, пригодный для повторного использования для нескольких запросов.333334Экземпляры [`BaseHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler) имеют только один метод, предназначенный для внешнего использования:335336#### `run(app)`337338Запускает указанное WSGI-приложение339340*app*341342.343344Все остальные методы [`BaseHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler) вызываются этим методом в процессе выполнения приложения и существуют в основном для того, чтобы позволить настраивать процесс.345346Следующие методы ОБЯЗАТЕЛЬНО должны быть переопределены в подклассе:347348#### `_write(data)`349350Буферизует байты351352*data*353354для передачи клиенту. Ничего страшного, если этот метод фактически передаёт данные;355356[`BaseHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler)357358просто разделяет операции записи и сброса для повышения эффективности, когда базовая система действительно имеет такое различие.359360#### `_flush()`361362Принудительно отправляет буферизованные данные клиенту. Ничего страшного, если этот метод ничего не делает (то есть если363364[`_write()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler._write)365366фактически отправляет данные).367368#### `get_stdin()`369370Возвращает объект входного потока, пригодный для использования в качестве371372`wsgi.input`373374текущего обрабатываемого запроса.375376#### `get_stderr()`377378Возвращает объект выходного потока, пригодный для использования в качестве379380`wsgi.errors`381382текущего обрабатываемого запроса.383384#### `add_cgi_vars()`385386Вставляет CGI-переменные для текущего запроса в атрибут387388`environ`389390.391392Вот некоторые другие методы и атрибуты, которые вы можете захотеть переопределить. Однако этот список является лишь кратким обзором и не включает каждый метод, который можно переопределить. Перед попыткой создать собственный подкласс [`BaseHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler) следует обратиться к строкам документации и исходному коду за дополнительной информацией.393394Атрибуты и методы для настройки окружения WSGI:395396#### `wsgi_multithread`397398Значение, используемое для переменной окружения399400`wsgi.multithread`401402. По умолчанию оно равно true в403404[`BaseHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler)405406, но может иметь другое значение по умолчанию (или устанавливаться конструктором) в других подклассах.407408#### `wsgi_multiprocess`409410Значение, используемое для переменной окружения411412`wsgi.multiprocess`413414. По умолчанию оно равно true в415416[`BaseHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler)417418, но может иметь другое значение по умолчанию (или устанавливаться конструктором) в других подклассах.419420#### `wsgi_run_once`421422Значение, которое будет использоваться для переменной окружения423424`wsgi.run_once`425426. По умолчанию оно равно false в427428[`BaseHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler)429430, но431432[`CGIHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.CGIHandler)433434по умолчанию устанавливает его в true.435436#### `os_environ`437438Переменные окружения по умолчанию, которые включаются в WSGI-окружение каждого запроса. По умолчанию это копия439440`os.environ`441442на момент импорта443444`wsgiref.handlers`445446, но подклассы могут создать свои собственные на уровне класса или экземпляра. Обратите внимание, что словарь следует считать доступным только для чтения, поскольку значение по умолчанию является общим для нескольких классов и экземпляров.447448#### `server_software`449450Если установлен атрибут451452[`origin_server`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server)453454, значение этого атрибута используется для установки переменной окружения WSGI по умолчанию455456`SERVER_SOFTWARE`457458, а также для установки заголовка459460`Server:`461462по умолчанию в HTTP-ответах. Он игнорируется для обработчиков (таких как463464[`BaseCGIHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler)465466и467468[`CGIHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.CGIHandler)469470), которые не являются исходными HTTP-серверами.471472#### `get_scheme()`473474Возвращает схему URL, используемую для текущего запроса. Реализация по умолчанию использует функцию475476`guess_scheme()`477478из модуля479480`wsgiref.util`481482, чтобы определить, должна ли схема быть «http» или «https», на основе переменных483484`environ`485486текущего запроса.487488#### `setup_environ()`489490Устанавливает атрибут491492`environ`493494в полностью заполненное WSGI-окружение. Реализация по умолчанию использует все вышеперечисленные методы и атрибуты, а также методы495496[`get_stdin()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stdin)497498,499500[`get_stderr()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stderr)501502и503504[`add_cgi_vars()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.add_cgi_vars)505506и атрибут507508[`wsgi_file_wrapper`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.wsgi_file_wrapper)509510. Она также вставляет ключ511512`SERVER_SOFTWARE`513514, если он отсутствует, при условии, что атрибут515516[`origin_server`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server)517518является истинным, а атрибут519520[`server_software`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.server_software)521522установлен.523524Методы и атрибуты для настройки обработки исключений:525526#### `log_exception(exc_info)`527528Записывает кортеж529530*exc\_info*531532в журнал сервера.533534*exc\_info*535536– это кортеж вида537538`(type, value, traceback)`539540. Реализация по умолчанию просто записывает трассировку в поток541542`wsgi.errors`543544запроса и сбрасывает его. Подклассы могут переопределить этот метод, чтобы изменить формат или перенаправить вывод, отправить трассировку администратору по электронной почте или выполнить любое другое действие, которое сочтут подходящим.545546#### `traceback_limit`547548Максимальное количество кадров, включаемых в трассировки, выводимые методом549550[`log_exception()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.log_exception)551552по умолчанию. Если553554`None`555556, включаются все кадры.557558#### `error_output(environ, start_response)`559560Этот метод представляет собой WSGI-приложение для генерации страницы ошибки для пользователя. Он вызывается только в том случае, если ошибка возникает до отправки заголовков клиенту.561562Этот метод может получить информацию о текущей ошибке с помощью `sys.exc_info()` и должен передавать эту информацию в *start\_response* при её вызове (как описано в разделе «Обработка ошибок» [**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html)).563564Реализация по умолчанию просто использует атрибуты [`error_status`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_status), [`error_headers`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_headers) и [`error_body`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_body) для генерации выходной страницы. Подклассы могут переопределить это, чтобы создавать более динамичный вывод ошибок.565566Однако с точки зрения безопасности не рекомендуется выводить диагностическую информацию любому пользователю; в идеале необходимо выполнить специальные действия для включения диагностического вывода, поэтому в реализации по умолчанию он отсутствует.567568#### `error_status`569570HTTP-статус, используемый для ответов об ошибках. Это должна быть строка статуса, как определено в571572[**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html)573574; по умолчанию используется код 500 и соответствующее сообщение.575576#### `error_headers`577578Заголовки HTTP, используемые для ответов об ошибках. Это должен быть список кортежей заголовков WSGI-ответа (579580`(name, value)`581582), как описано в583584[**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html)585586. Список по умолчанию просто устанавливает тип содержимого в587588`text/plain`589590.591592#### `error_body`593594Тело ответа об ошибке. Это должна быть строка тела HTTP-ответа. По умолчанию используется обычный текст: «Произошла ошибка сервера. Пожалуйста, свяжитесь с администратором».595596Методы и атрибуты для [**PEP 333**](https://python-all.ru/3.1/library/wsgiref.html) функции «Необязательная работа с файлами на уровне платформы»:597598#### `wsgi_file_wrapper`599600Фабрика601602`wsgi.file_wrapper`603604или605606`None`607608. Значением этого атрибута по умолчанию является класс609610[`wsgiref.util.FileWrapper`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.util.FileWrapper)611612.613614#### `sendfile()`615616Переопределите для реализации передачи файлов, специфичной для платформы. Этот метод вызывается только в том случае, если возвращаемое значение приложения является экземпляром класса, указанного атрибутом617618[`wsgi_file_wrapper`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.wsgi_file_wrapper)619620. Он должен вернуть истинное значение, если файл удалось успешно передать, чтобы код передачи по умолчанию не выполнялся. Реализация по умолчанию этого метода просто возвращает ложное значение.621622Разные методы и атрибуты:623624#### `origin_server`625626Этот атрибут должен быть установлен в истинное значение, если методы [`_write()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler._write) и [`_flush()`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler._flush) обработчика используются для прямой связи с клиентом, а не через шлюзовой протокол, подобный CGI, который ожидает HTTP-статус в специальном заголовке `Status:`.627628Значение этого атрибута по умолчанию равно true в [`BaseHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler), но false в [`BaseCGIHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler) и [`CGIHandler`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.CGIHandler).629630#### `http_version`631632Если633634[`origin_server`](https://python-all.ru/3.1/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server)635636истинно, этот строковый атрибут используется для установки версии HTTP ответа, отправляемого клиенту. По умолчанию он равен637638`"1.0"`639640.641642## 20.4.6. Примеры643644Это рабочее WSGI-приложение «Hello World»:645646```python647from wsgiref.simple_server import make_server648649# Каждое WSGI-приложение должно иметь объект приложения – вызываемый650# объект, который принимает два аргумента. Для этого651# можно использовать функцию (обратите внимание: можно не только функцию, но и, например, класс)652# использовать, например, класс). Первый аргумент, передаваемый функции,653# является словарём, содержащим переменные окружения в стиле CGI и654# вторая переменная – это вызываемый объект (см. PEP 333).655def hello_world_app(environ, start_response):656 status = b'200 OK' # HTTP-статус657 headers = [(b'Content-type', b'text/plain; charset=utf-8')] # HTTP-заголовки658 start_response(status, headers)659660 # Возвращаемый объект будет выведен661 return [b"Hello World"]662663httpd = make_server('', 8000, hello_world_app)664print("Serving on port 8000...")665666# Обслуживать до завершения процесса667httpd.serve_forever()668```669