wsgiref.md
1> **Источник:** https://python-all.ru/3.12/library/wsgiref.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `wsgiref` – утилиты WSGI и эталонная реализация89**Исходный код:** [Lib/wsgiref](https://python-all.ru/3.12/library/wsgiref.html)1011---1213> **Предупреждение**14>15> [`wsgiref`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref) – эталонная реализация, не предназначенная для использования в production. Модуль содержит только базовые проверки безопасности.1617Интерфейс шлюза веб-сервера (WSGI) – это стандартный интерфейс между веб-сервером и веб-приложениями на Python. Наличие стандартного интерфейса упрощает использование приложения, поддерживающего WSGI, с различными веб-серверами.1819Только разработчики веб-серверов и фреймворков должны знать все тонкости и пограничные случаи дизайна WSGI. Чтобы установить WSGI-приложение или написать веб-приложение с помощью готового фреймворка, не нужно понимать каждую деталь WSGI.2021[`wsgiref`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref) – эталонная реализация спецификации WSGI, которую можно использовать для добавления поддержки WSGI в веб-сервер или фреймворк. Она предоставляет утилиты для работы с переменными окружения WSGI и заголовками ответов, базовые классы для реализации серверов WSGI, демонстрационный HTTP-сервер, обслуживающий WSGI-приложения, типы для статической проверки типов и инструмент проверки, который проверяет серверы и приложения WSGI на соответствие спецификации WSGI ([**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html)).2223См. [wsgi.readthedocs.io](https://python-all.ru/3.12/library/wsgiref.html) для получения дополнительной информации о WSGI и ссылок на учебные пособия и другие ресурсы.2425## [`wsgiref.util`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.util) – утилиты окружения WSGI2627Этот модуль предоставляет различные утилиты для работы с окружением WSGI. Окружение WSGI – это словарь, содержащий переменные HTTP-запроса, как описано в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html). Все функции, принимающие параметр *environ*, ожидают словарь, совместимый с WSGI; пожалуйста, обратитесь к [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html) для подробной спецификации и [`WSGIEnvironment`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.types.WSGIEnvironment) для псевдонима типа, который можно использовать в аннотациях типов.2829#### `wsgiref.util.guess_scheme(environ)`3031Возвращает предположение о том, должно ли `wsgi.url_scheme` быть "http" или "https", проверяя переменную окружения `HTTPS` в словаре *environ*. Возвращаемое значение – строка.3233Эта функция полезна при создании шлюза, оборачивающего CGI или подобный CGI протокол, например FastCGI. Обычно серверы, реализующие такие протоколы, устанавливают переменную `HTTPS` со значением “1”, “yes” или “on”, когда запрос получен через SSL. Поэтому функция возвращает “https”, если найдено такое значение, и “http” в противном случае.3435#### `wsgiref.util.request_uri(environ, include_query=True)`3637Возвращает полный URI запроса, опционально включая строку запроса, используя алгоритм, описанный в разделе «URL Reconstruction» [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html). Если *include\_query* равно false, строка запроса не включается в результирующий URI.3839#### `wsgiref.util.application_uri(environ)`4041Аналогично [`request_uri()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.util.request_uri), за исключением того, что переменные `PATH_INFO` и `QUERY_STRING` игнорируются. Результат – базовый URI объекта приложения, адресованного запросом.4243#### `wsgiref.util.shift_path_info(environ)`4445Перемещает одно имя из `PATH_INFO` в `SCRIPT_NAME` и возвращает это имя. Словарь *environ* изменяется *на месте*; используйте копию, если нужно сохранить исходные `PATH_INFO` или `SCRIPT_NAME` неизменными.4647Если в `PATH_INFO` не осталось сегментов пути, возвращается `None`.4849Обычно эта процедура используется для обработки каждой части пути URI запроса, например, чтобы рассматривать путь как последовательность ключей словаря. Эта процедура изменяет переданное окружение, чтобы сделать его пригодным для вызова другого WSGI-приложения, расположенного по целевому URI. Например, если есть WSGI-приложение по адресу `/foo`, и путь URI запроса – `/foo/bar/baz`, и WSGI-приложение по адресу `/foo` вызывает [`shift_path_info()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.util.shift_path_info), оно получит строку “bar”, а окружение будет обновлено для передачи WSGI-приложению по адресу `/foo/bar`. То есть, `SCRIPT_NAME` изменится с `/foo` на `/foo/bar`, а `PATH_INFO` изменится с `/bar/baz` на `/baz`.5051Когда `PATH_INFO` представляет собой просто “/”, эта процедура возвращает пустую строку и добавляет завершающий слеш к `SCRIPT_NAME`, хотя пустые сегменты пути обычно игнорируются, и `SCRIPT_NAME` обычно не заканчивается слешем. Это преднамеренное поведение, чтобы гарантировать, что приложение сможет отличить URI, заканчивающиеся на `/x`, от URI, заканчивающихся на `/x/`, при использовании этой процедуры для обхода объектов.5253#### `wsgiref.util.setup_testing_defaults(environ)`5455Обновляет *environ* простыми значениями по умолчанию для целей тестирования.5657Эта процедура добавляет различные параметры, необходимые для WSGI, включая `HTTP_HOST`, `SERVER_NAME`, `SERVER_PORT`, `REQUEST_METHOD`, `SCRIPT_NAME`, `PATH_INFO` и все переменные `wsgi.*`, определённые в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html). Она только задаёт значения по умолчанию и не заменяет существующие настройки этих переменных.5859Эта процедура предназначена для упрощения настройки фиктивных окружений в модульных тестах серверов и приложений WSGI. Её НЕ следует использовать в реальных серверах или приложениях WSGI, поскольку данные являются фиктивными!6061Пример использования (см. также [`demo_app()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.demo_app) для другого примера):6263```python64from wsgiref.util import setup_testing_defaults65from wsgiref.simple_server import make_server6667# Относительно простое WSGI-приложение. Оно выведет68# словарь окружения после обновления с помощью setup_testing_defaults69def simple_app(environ, start_response):70 setup_testing_defaults(environ)7172 status = '200 OK'73 headers = [('Content-type', 'text/plain; charset=utf-8')]7475 start_response(status, headers)7677 ret = [("%s: %s\n" % (key, value)).encode("utf-8")78 for key, value in environ.items()]79 return ret8081with make_server('', 8000, simple_app) as httpd:82 print("Serving on port 8000...")83 httpd.serve_forever()84```8586В дополнение к функциям окружения, описанным выше, модуль [`wsgiref.util`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.util) также предоставляет следующие вспомогательные утилиты:8788#### `wsgiref.util.is_hop_by_hop(header_name)`8990Возвращает `True`, если ‘header\_name’ является HTTP/1.1 «Hop-by-Hop»-заголовком, как определено в [**RFC 2616**](https://python-all.ru/3.12/library/wsgiref.html).9192#### `class wsgiref.util.FileWrapper(filelike, blksize=8192)`9394Конкретная реализация протокола [`wsgiref.types.FileWrapper`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.types.FileWrapper), используемого для преобразования файлоподобного объекта в [итератор](https://python-all.ru/3.12/glossary.html#term-iterator). Результирующие объекты являются [итерируемыми](https://python-all.ru/3.12/glossary.html#term-iterable). При итерации по объекту необязательный параметр *blksize* многократно передаётся методу `read()` объекта *filelike*, чтобы получать байтовые строки и возвращать их. Когда `read()` возвращает пустую байтовую строку, итерация завершается и не может быть возобновлена.9596Если *файлоподобный объект* имеет метод `close()`, возвращаемый объект также будет иметь метод `close()`, и при вызове он будет вызывать метод `close()` объекта *файлоподобный объект*.9798Пример использования:99100```python101from io import StringIO102from wsgiref.util import FileWrapper103104# В качестве файлоподобного объекта используется буфер StringIO105filelike = StringIO("This is an example file-like object"*10)106wrapper = FileWrapper(filelike, blksize=5)107108for chunk in wrapper:109 print(chunk)110```111112Изменено в версии 3.11: Поддержка метода [`__getitem__()`](https://python-all.ru/3.12/reference/datamodel.html#object.__getitem__) удалена.113114## [`wsgiref.headers`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.headers) – инструменты для работы с заголовками ответа WSGI115116Этот модуль предоставляет единственный класс [`Headers`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.headers.Headers) для удобной работы с заголовками ответов WSGI через интерфейс, напоминающий словарь (mapping).117118#### `class wsgiref.headers.Headers([headers])`119120Создаёт объект, похожий на словарь, оборачивающий *headers*, который должен быть списком кортежей (имя заголовка, значение), как описано в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html). По умолчанию *headers* равен пустому списку.121122Объекты [`Headers`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.headers.Headers) поддерживают стандартные операции отображения, включая [`__getitem__()`](https://python-all.ru/3.12/reference/datamodel.html#object.__getitem__), [`get()`](https://python-all.ru/3.12/library/stdtypes.html#dict.get), [`__setitem__()`](https://python-all.ru/3.12/reference/datamodel.html#object.__setitem__), [`setdefault()`](https://python-all.ru/3.12/library/stdtypes.html#dict.setdefault), [`__delitem__()`](https://python-all.ru/3.12/reference/datamodel.html#object.__delitem__) и [`__contains__()`](https://python-all.ru/3.12/reference/datamodel.html#object.__contains__). Для каждого из этих методов ключом является имя заголовка (регистронезависимое), а значением – первое значение, связанное с этим именем. При установке заголовка все существующие значения этого заголовка удаляются, а новое значение добавляется в конец обёрнутого списка. Существующий порядок заголовков в основном сохраняется, новые заголовки добавляются в конец обёрнутого списка.123124В отличие от словаря, объекты [`Headers`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.headers.Headers) не вызывают ошибку при попытке получить или удалить ключ, которого нет в обёрнутом списке заголовков. Получение несуществующего заголовка просто возвращает `None`, а удаление несуществующего заголовка ничего не делает.125126Объекты [`Headers`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.headers.Headers) также поддерживают методы `keys()`, `values()` и `items()`. Списки, возвращаемые `keys()` и `items()`, могут содержать один и тот же ключ несколько раз, если заголовок многозначный. Длина (`len()`) объекта [`Headers`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.headers.Headers) равна длине его `items()`, которая равна длине обёрнутого списка заголовков. По сути, метод `items()` просто возвращает копию обёрнутого списка заголовков.127128Вызов `bytes()` для объекта [`Headers`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.headers.Headers) возвращает форматированную байтовую строку, пригодную для передачи в качестве HTTP-заголовков ответа. Каждый заголовок размещается на отдельной строке со своим значением, разделёнными двоеточием и пробелом. Каждая строка завершается символами возврата каретки и перевода строки, а байтовая строка завершается пустой строкой.129130В дополнение к интерфейсу отображения и функциям форматирования, объекты [`Headers`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.headers.Headers) также имеют следующие методы для запроса и добавления многозначных заголовков, а также для добавления заголовков с MIME-параметрами:131132#### `get_all(name)`133134Возвращает список всех значений для указанного заголовка.135136Возвращаемый список будет отсортирован в порядке появления в исходном списке заголовков или добавления в данный экземпляр, и может содержать дубликаты. Любые удалённые и повторно вставленные поля всегда добавляются в конец списка заголовков. Если полей с указанным именем не существует, возвращается пустой список.137138#### `add_header(name, value, **_params)`139140Добавляет (возможно, многозначный) заголовок с необязательными MIME-параметрами, задаваемыми через именованные аргументы.141142*name* – это добавляемое поле заголовка. Именованные аргументы можно использовать для установки MIME-параметров поля заголовка. Каждый параметр должен быть строкой или `None`. Подчёркивания в именах параметров заменяются на дефисы, поскольку дефисы недопустимы в идентификаторах Python, но многие имена MIME-параметров содержат дефисы. Если значение параметра – строка, оно добавляется к параметрам значения заголовка в виде `name="value"`. Если это `None`, добавляется только имя параметра. (Это используется для MIME-параметров без значения.) Пример использования:143144```python145h.add_header('content-disposition', 'attachment', filename='bud.gif')146```147148Приведённый выше код добавит заголовок, который будет выглядеть так:149150```python151Content-Disposition: attachment; filename="bud.gif"152```153154Изменено в версии 3.5: Параметр *headers* стал необязательным.155156## [`wsgiref.simple_server`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.simple_server) – простой WSGI HTTP-сервер157158Этот модуль реализует простой HTTP-сервер (на базе [`http.server`](https://python-all.ru/3.12/library/http.server.html#module-http.server)), обслуживающий WSGI-приложения. Каждый экземпляр сервера обслуживает одно WSGI-приложение на заданном хосте и порту. Если требуется обслуживать несколько приложений на одном хосте и порту, следует создать WSGI-приложение, которое анализирует `PATH_INFO`, чтобы выбрать, какое приложение вызывать для каждого запроса. (Например, с помощью функции `shift_path_info()` из [`wsgiref.util`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.util).)159160#### `wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler)`161162Создаёт новый WSGI-сервер, прослушивающий *host* и *port*, принимающий соединения для *app*. Возвращаемое значение – экземпляр указанного *server\_class*, который будет обрабатывать запросы с помощью заданного *handler\_class*. *app* должен быть объектом WSGI-приложения, как определено в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html).163164Пример использования:165166```python167from wsgiref.simple_server import make_server, demo_app168169with make_server('', 8000, demo_app) as httpd:170 print("Serving HTTP on port 8000...")171172 # Отвечать на запросы до завершения процесса173 httpd.serve_forever()174175 # Альтернатива: обработать один запрос и завершить работу176 httpd.handle_request()177```178179#### `wsgiref.simple_server.demo_app(environ, start_response)`180181Эта функция представляет собой небольшое, но полноценное WSGI-приложение, которое возвращает текстовую страницу с сообщением «Hello world!» и списком пар ключ/значение, переданных в параметре *environ*. Она полезна для проверки того, что WSGI-сервер (например, [`wsgiref.simple_server`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.simple_server)) способен корректно запустить простое WSGI-приложение.182183Вызываемый объект *start\_response* должен следовать протоколу [`StartResponse`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.types.StartResponse).184185#### `class wsgiref.simple_server.WSGIServer(server_address, RequestHandlerClass)`186187Создаёт экземпляр [`WSGIServer`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.WSGIServer). *server\_address* должен быть кортежем `(host,port)`, а *RequestHandlerClass* – подклассом [`http.server.BaseHTTPRequestHandler`](https://python-all.ru/3.12/library/http.server.html#http.server.BaseHTTPRequestHandler), который будет использоваться для обработки запросов.188189Обычно нет необходимости вызывать этот конструктор, поскольку функция [`make_server()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.make_server) берёт на себя все детали.190191[`WSGIServer`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.WSGIServer) является подклассом [`http.server.HTTPServer`](https://python-all.ru/3.12/library/http.server.html#http.server.HTTPServer), поэтому все его методы (такие как `serve_forever()` и `handle_request()`) доступны. [`WSGIServer`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.WSGIServer) также предоставляет следующие специфичные для WSGI методы:192193#### `set_app(application)`194195Устанавливает вызываемый объект *application* в качестве WSGI-приложения, которое будет получать запросы.196197#### `get_app()`198199Возвращает текущий установленный вызываемый объект приложения.200201Однако обычно нет необходимости использовать эти дополнительные методы, так как [`set_app()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.WSGIServer.set_app) обычно вызывается [`make_server()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.make_server), а [`get_app()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.WSGIServer.get_app) существует в основном для удобства экземпляров обработчиков запросов.202203#### `class wsgiref.simple_server.WSGIRequestHandler(request, client_address, server)`204205Создаёт HTTP-обработчик для заданного *request* (т.е. сокета), *client\_address* (кортеж `(host,port)`) и *server* (экземпляр [`WSGIServer`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.WSGIServer)).206207Нет необходимости создавать экземпляры этого класса напрямую; они создаются автоматически по мере необходимости объектами [`WSGIServer`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.WSGIServer). Однако можно создать подкласс этого класса и передать его в качестве *handler\_class* функции [`make_server()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.make_server). Некоторые методы, которые могут быть переопределены в подклассах:208209#### `get_environ()`210211Возвращает словарь [`WSGIEnvironment`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.types.WSGIEnvironment) для запроса. Реализация по умолчанию копирует содержимое атрибута `base_environ` объекта [`WSGIServer`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.simple_server.WSGIServer), а затем добавляет различные заголовки, полученные из HTTP-запроса. Каждый вызов этого метода должен возвращать новый словарь, содержащий все соответствующие переменные окружения CGI, как указано в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html).212213#### `get_stderr()`214215Возвращает объект, который следует использовать в качестве потока `wsgi.errors`. Реализация по умолчанию просто возвращает `sys.stderr`.216217#### `handle()`218219Обрабатывает HTTP-запрос. Реализация по умолчанию создаёт экземпляр обработчика, используя класс [`wsgiref.handlers`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.handlers) для реализации фактического интерфейса WSGI-приложения.220221## [`wsgiref.validate`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.validate) – средство проверки соответствия WSGI222223При создании новых объектов WSGI-приложений, фреймворков, серверов или промежуточного ПО может быть полезно проверить соответствие нового кода с помощью [`wsgiref.validate`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.validate). Этот модуль предоставляет функцию, которая создаёт объекты WSGI-приложений, проверяющие взаимодействие между WSGI-сервером или шлюзом и объектом WSGI-приложения, чтобы проверить обе стороны на соответствие протоколу.224225Обратите внимание, что эта утилита не гарантирует полного соответствия [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html); отсутствие ошибок от этого модуля не обязательно означает, что ошибок не существует. Однако если этот модуль выдаёт ошибку, то практически наверняка либо сервер, либо приложение не соответствует требованиям на 100%.226227Этот модуль основан на модуле `paste.lint` из библиотеки «Python Paste» Иана Бикинга.228229#### `wsgiref.validate.validator(application)`230231Оборачивает *application* и возвращает новый объект WSGI-приложения. Возвращённое приложение будет перенаправлять все запросы исходному *application* и проверять, что и *application*, и вызывающий его сервер соответствуют спецификации WSGI и [**RFC 2616**](https://python-all.ru/3.12/library/wsgiref.html).232233Любое обнаруженное несоответствие приводит к возбуждению [`AssertionError`](https://python-all.ru/3.12/library/exceptions.html#AssertionError); однако обратите внимание, что обработка этих ошибок зависит от сервера. Например, [`wsgiref.simple_server`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.simple_server) и другие серверы на основе [`wsgiref.handlers`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.handlers) (которые не переопределяют методы обработки ошибок для других действий) просто выведут сообщение о том, что произошла ошибка, и отправят трассировку в `sys.stderr` или другой поток ошибок.234235Эта обёртка также может генерировать вывод с помощью модуля [`warnings`](https://python-all.ru/3.12/library/warnings.html#module-warnings), чтобы указать на поведение, которое вызывает сомнения, но может и не быть явно запрещённым [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html). Если такие предупреждения не подавлены с помощью параметров командной строки Python или API [`warnings`](https://python-all.ru/3.12/library/warnings.html#module-warnings), они будут записаны в `sys.stderr` (*не* в `wsgi.errors`, если только это не один и тот же объект).236237Пример использования:238239```python240from wsgiref.validate import validator241from wsgiref.simple_server import make_server242243# Наш вызываемый объект, который намеренно не соответствует244# стандарту, поэтому валидатор выдаст ошибку245def simple_app(environ, start_response):246 status = '200 OK' # HTTP-статус247 headers = [('Content-type', 'text/plain')] # HTTP-заголовки248 start_response(status, headers)249250 # Это приведёт к ошибке, потому что нужно вернуть список, и251 # валидатор сообщит об этом252 return b"Hello World"253254# Это приложение, обёрнутое в валидатор255validator_app = validator(simple_app)256257with make_server('', 8000, validator_app) as httpd:258 print("Listening on port 8000....")259 httpd.serve_forever()260```261262## [`wsgiref.handlers`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.handlers) – базовые классы серверов/шлюзов263264Этот модуль предоставляет базовые классы обработчиков для реализации WSGI-серверов и шлюзов. Эти базовые классы берут на себя большую часть работы по взаимодействию с WSGI-приложением при условии, что им предоставлено окружение, подобное CGI, а также потоки ввода, вывода и ошибок.265266#### `class wsgiref.handlers.CGIHandler`267268Вызов на основе CGI через `sys.stdin`, `sys.stdout`, `sys.stderr` и `os.environ`. Это полезно, когда есть WSGI-приложение, которое нужно запустить как CGI-скрипт. Просто вызовите `CGIHandler().run(app)`, где `app` – это объект WSGI-приложения, которое требуется вызвать.269270Этот класс является подклассом [`BaseCGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler), который устанавливает `wsgi.run_once` в true, `wsgi.multithread` в false, а `wsgi.multiprocess` в true и всегда использует [`sys`](https://python-all.ru/3.12/library/sys.html#module-sys) и [`os`](https://python-all.ru/3.12/library/os.html#module-os) для получения необходимых CGI-потоков и окружения.271272#### `class wsgiref.handlers.IISCGIHandler`273274Специализированная альтернатива [`CGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.CGIHandler) для использования при развёртывании на веб-сервере Microsoft IIS без установки опции конфигурации allowPathInfo (IIS\>=7) или метабазы allowPathInfoForScriptMappings (IIS\<7).275276По умолчанию IIS предоставляет `PATH_INFO`, который дублирует `SCRIPT_NAME` в начале, что вызывает проблемы для WSGI-приложений, желающих реализовать маршрутизацию. Этот обработчик удаляет любой такой дублированный путь.277278IIS можно настроить на передачу правильного `PATH_INFO`, но это вызывает другую ошибку, при которой `PATH_TRANSLATED` оказывается неверным. К счастью, эта переменная редко используется и не гарантируется WSGI. Однако на IIS\<7 настройка может быть выполнена только на уровне виртуального хоста, затрагивая все остальные сопоставления скриптов, многие из которых ломаются при воздействии ошибки `PATH_TRANSLATED`. По этой причине IIS\<7 почти никогда не разворачивается с исправлением (даже IIS7 редко его использует, так как для него до сих пор нет пользовательского интерфейса).279280У CGI-кода нет способа определить, была ли установлена опция, поэтому предоставляется отдельный класс обработчика. Он используется так же, как [`CGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.CGIHandler), то есть вызовом `IISCGIHandler().run(app)`, где `app` – это объект WSGI-приложения, которое требуется вызвать.281282Добавлено в версии 3.2.283284#### `class wsgiref.handlers.BaseCGIHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)`285286Аналогично [`CGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.CGIHandler), но вместо использования модулей [`sys`](https://python-all.ru/3.12/library/sys.html#module-sys) и [`os`](https://python-all.ru/3.12/library/os.html#module-os) окружение CGI и потоки ввода-вывода задаются явно. Значения *multithread* и *multiprocess* используются для установки флагов `wsgi.multithread` и `wsgi.multiprocess` для любых приложений, запускаемых экземпляром обработчика.287288Этот класс является подклассом [`SimpleHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.SimpleHandler), предназначенным для использования с программами, отличными от HTTP-«исходных серверов». Если вы пишете реализацию шлюзового протокола (например, CGI, FastCGI, SCGI и т.д.), которая использует заголовок `Status:` для отправки HTTP-статуса, то, вероятно, стоит создать подкласс этого класса, а не [`SimpleHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.SimpleHandler).289290#### `class wsgiref.handlers.SimpleHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)`291292Похож на [`BaseCGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler), но предназначен для использования с исходными HTTP-серверами. Если вы пишете реализацию HTTP-сервера, то, вероятно, стоит создать подкласс этого класса, а не [`BaseCGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler).293294Этот класс является подклассом [`BaseHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler). Он переопределяет методы `__init__()`, [`get_stdin()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stdin), [`get_stderr()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stderr), [`add_cgi_vars()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.add_cgi_vars), [`_write()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler._write) и [`_flush()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler._flush) для поддержки явной установки окружения и потоков через конструктор. Предоставленные окружение и потоки сохраняются в атрибутах `stdin`, `stdout`, `stderr` и `environ`.295296Метод [`write()`](https://python-all.ru/3.12/library/io.html#io.BufferedIOBase.write) объекта *stdout* должен записывать каждый фрагмент полностью, как [`io.BufferedIOBase`](https://python-all.ru/3.12/library/io.html#io.BufferedIOBase).297298#### `class wsgiref.handlers.BaseHandler`299300Это абстрактный базовый класс для запуска WSGI-приложений. Каждый экземпляр будет обрабатывать один HTTP-запрос, хотя в принципе можно создать подкласс, пригодный для повторного использования для нескольких запросов.301302Экземпляры [`BaseHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler) имеют только один метод, предназначенный для внешнего использования:303304#### `run(app)`305306Запускает указанное WSGI-приложение *app*.307308Все остальные методы [`BaseHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler) вызываются этим методом в процессе выполнения приложения и, по существу, существуют для возможности настройки процесса.309310Следующие методы ОБЯЗАТЕЛЬНО должны быть переопределены в подклассе:311312#### `_write(data)`313314Буферизует байты *data* для передачи клиенту. Нормально, если этот метод фактически передаёт данные; [`BaseHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler) просто разделяет операции записи и сброса для повышения эффективности, когда базовая система действительно имеет такое различие.315316#### `_flush()`317318Принудительно отправляет буферизованные данные клиенту. Нормально, если этот метод ничего не делает (т.е. если [`_write()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler._write) фактически отправляет данные).319320#### `get_stdin()`321322Возвращает объект, совместимый с [`InputStream`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.types.InputStream), пригодный для использования в качестве `wsgi.input` обрабатываемого в данный момент запроса.323324#### `get_stderr()`325326Возвращает объект, совместимый с [`ErrorStream`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.types.ErrorStream), пригодный для использования в качестве `wsgi.errors` обрабатываемого в данный момент запроса.327328#### `add_cgi_vars()`329330Вставляет переменные CGI для текущего запроса в атрибут `environ`.331332Вот некоторые другие методы и атрибуты, которые вы можете захотеть переопределить. Однако этот список является лишь кратким обзором и не включает все методы, которые можно переопределить. Перед попыткой создать собственный подкласс [`BaseHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler) следует ознакомиться с дополнительной информацией в строках документации и исходном коде.333334Атрибуты и методы для настройки окружения WSGI:335336#### `wsgi_multithread`337338Значение, которое будет использоваться для переменной окружения `wsgi.multithread`. По умолчанию оно равно true в [`BaseHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler), но может иметь другое значение по умолчанию (или быть установлено конструктором) в других подклассах.339340#### `wsgi_multiprocess`341342Значение, которое будет использоваться для переменной окружения `wsgi.multiprocess`. По умолчанию оно равно true в [`BaseHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler), но может иметь другое значение по умолчанию (или быть установлено конструктором) в других подклассах.343344#### `wsgi_run_once`345346Значение, которое будет использоваться для переменной окружения `wsgi.run_once`. По умолчанию оно равно false в [`BaseHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler), но [`CGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.CGIHandler) устанавливает его в true по умолчанию.347348#### `os_environ`349350Переменные окружения по умолчанию, которые будут включены в WSGI-окружение каждого запроса. По умолчанию это копия `os.environ` на момент импорта [`wsgiref.handlers`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.handlers), но подклассы могут создать собственные на уровне класса или экземпляра. Обратите внимание, что словарь следует считать доступным только для чтения, поскольку значение по умолчанию совместно используется несколькими классами и экземплярами.351352#### `server_software`353354Если атрибут [`origin_server`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server) установлен, его значение используется для установки переменной окружения WSGI `SERVER_SOFTWARE` по умолчанию, а также для установки заголовка `Server:` по умолчанию в HTTP-ответах. Он игнорируется для обработчиков (таких как [`BaseCGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler) и [`CGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.CGIHandler)), которые не являются исходными HTTP-серверами.355356Изменено в версии 3.3: Термин «Python» заменён на термин, специфичный для реализации, например «CPython», «Jython» и т.д.357358#### `get_scheme()`359360Возвращает схему URL, используемую для текущего запроса. Реализация по умолчанию использует функцию `guess_scheme()` из [`wsgiref.util`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.util), чтобы определить, должна ли схема быть «http» или «https», на основе переменных `environ` текущего запроса.361362#### `setup_environ()`363364Устанавливает атрибут `environ` в полностью заполненное окружение WSGI. Реализация по умолчанию использует все вышеперечисленные методы и атрибуты, а также методы [`get_stdin()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stdin), [`get_stderr()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stderr) и [`add_cgi_vars()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.add_cgi_vars), и атрибут [`wsgi_file_wrapper`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.wsgi_file_wrapper). Она также вставляет ключ `SERVER_SOFTWARE`, если он отсутствует, при условии, что атрибут [`origin_server`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server) имеет истинное значение, а атрибут [`server_software`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.server_software) установлен.365366Методы и атрибуты для настройки обработки исключений:367368#### `log_exception(exc_info)`369370Записывает кортеж *exc\_info* в журнал сервера. *exc\_info* – это кортеж `(type, value, traceback)`. Реализация по умолчанию просто записывает трассировку в поток `wsgi.errors` запроса и сбрасывает его. Подклассы могут переопределить этот метод, чтобы изменить формат или перенаправить вывод, отправить трассировку администратору по почте или выполнить любое другое действие, которое сочтут подходящим.371372#### `traceback_limit`373374Максимальное количество фреймов, включаемых в трассировки, выводимые методом [`log_exception()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.log_exception) по умолчанию. Если `None`, включаются все фреймы.375376#### `error_output(environ, start_response)`377378Этот метод представляет собой WSGI-приложение для генерации страницы ошибки для пользователя. Он вызывается только в том случае, если ошибка возникает до отправки заголовков клиенту.379380Этот метод может получить доступ к текущей ошибке с помощью `sys.exception()` и должен передавать эту информацию в *start\_response* при его вызове (как описано в разделе «Обработка ошибок» в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html)). В частности, вызываемый объект *start\_response* должен следовать протоколу [`StartResponse`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.types.StartResponse).381382Реализация по умолчанию просто использует атрибуты [`error_status`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_status), [`error_headers`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_headers) и [`error_body`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_body) для генерации выходной страницы. Подклассы могут переопределить это для создания более динамичного вывода ошибок.383384Однако с точки зрения безопасности не рекомендуется выводить диагностическую информацию любому пользователю; в идеале необходимо выполнить специальные действия для включения диагностического вывода, поэтому в реализации по умолчанию он отсутствует.385386#### `error_status`387388HTTP-статус, используемый для ответов об ошибках. Это должна быть строка статуса, как определено в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html); по умолчанию это код 500 и соответствующее сообщение.389390#### `error_headers`391392HTTP-заголовки, используемые для ответов об ошибках. Это должен быть список заголовков ответа WSGI (кортежи `(name, value)`), как описано в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html). Список по умолчанию просто устанавливает тип содержимого `text/plain`.393394#### `error_body`395396Тело ответа об ошибке. Это должна быть байтовая строка тела HTTP-ответа. По умолчанию это обычный текст: «A server error occurred. Please contact the administrator.»397398Методы и атрибуты для функции «Optional Platform-Specific File Handling» из [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html):399400#### `wsgi_file_wrapper`401402Фабрика `wsgi.file_wrapper`, совместимая с [`wsgiref.types.FileWrapper`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.types.FileWrapper) или `None`. Значение по умолчанию этого атрибута – класс [`wsgiref.util.FileWrapper`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.util.FileWrapper).403404#### `sendfile()`405406Переопределите для реализации передачи файлов, зависящей от платформы. Этот метод вызывается только в том случае, если возвращаемое значение приложения является экземпляром класса, указанного атрибутом [`wsgi_file_wrapper`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.wsgi_file_wrapper). Он должен возвращать истинное значение, если файл был успешно передан, чтобы код передачи по умолчанию не выполнялся. Реализация этого метода по умолчанию просто возвращает ложное значение.407408Разные методы и атрибуты:409410#### `origin_server`411412Этот атрибут должен быть установлен в истинное значение, если [`_write()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler._write) и [`_flush()`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler._flush) обработчика используются для прямой связи с клиентом, а не через шлюзовой протокол типа CGI, который ожидает HTTP-статус в специальном заголовке `Status:`.413414Значение этого атрибута по умолчанию равно true в [`BaseHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler), но false в [`BaseCGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler) и [`CGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.CGIHandler).415416#### `http_version`417418Если [`origin_server`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server) равно True, этот строковый атрибут используется для установки HTTP-версии ответа, отправляемого клиенту. По умолчанию он равен `"1.0"`.419420#### `wsgiref.handlers.read_environ()`421422Перекодирует CGI-переменные из `os.environ` в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html) строки «bytes in unicode» и возвращает новый словарь. Эта функция используется [`CGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.CGIHandler) и [`IISCGIHandler`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.handlers.IISCGIHandler) вместо прямого использования `os.environ`, который не обязательно совместим с WSGI на всех платформах и веб-серверах, использующих Python 3 – в частности, на тех, где реальное окружение ОС в Unicode (например, Windows), или на тех, где окружение – байты, но системная кодировка, используемая Python для его декодирования, отлична от ISO-8859-1 (например, Unix-системы с UTF-8).423424При реализации собственного CGI-обработчика, вероятно, следует использовать эту процедуру вместо прямого копирования значений из `os.environ`.425426Добавлено в версии 3.2.427428## [`wsgiref.types`](https://python-all.ru/3.12/library/wsgiref.html#module-wsgiref.types) – типы WSGI для статической проверки типов429430Этот модуль предоставляет различные типы для статической проверки типов, как описано в [**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html).431432Добавлено в версии 3.12.433434#### `class wsgiref.types.StartResponse`435436[`typing.Protocol`](https://python-all.ru/3.12/library/typing.html#typing.Protocol), описывающий [**start\_response()**](https://python-all.ru/3.12/library/wsgiref.html) вызываемые объекты ([**PEP 3333**](https://python-all.ru/3.12/library/wsgiref.html)).437438#### `wsgiref.types.WSGIEnvironment`439440Псевдоним типа, описывающий словарь окружения WSGI.441442#### `wsgiref.types.WSGIApplication`443444Псевдоним типа, описывающий вызываемый объект приложения WSGI.445446#### `class wsgiref.types.InputStream`447448[`typing.Protocol`](https://python-all.ru/3.12/library/typing.html#typing.Protocol), описывающий [**входной поток WSGI**](https://python-all.ru/3.12/library/wsgiref.html).449450#### `class wsgiref.types.ErrorStream`451452[`typing.Protocol`](https://python-all.ru/3.12/library/typing.html#typing.Protocol), описывающий [**поток ошибок WSGI**](https://python-all.ru/3.12/library/wsgiref.html).453454#### `class wsgiref.types.FileWrapper`455456[`typing.Protocol`](https://python-all.ru/3.12/library/typing.html#typing.Protocol), описывающий [**обёртку файла**](https://python-all.ru/3.12/library/wsgiref.html). Для конкретной реализации этого протокола см. [`wsgiref.util.FileWrapper`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.util.FileWrapper).457458## Примеры459460Это рабочий пример WSGI-приложения «Hello World», в котором вызываемый объект *start\_response* должен следовать протоколу [`StartResponse`](https://python-all.ru/3.12/library/wsgiref.html#wsgiref.types.StartResponse):461462```python463"""464Каждое WSGI-приложение должно иметь объект приложения – вызываемый465объект, который принимает два аргумента. Для этого466можно использовать функцию (обратите внимание: можно не только функцию, но и, например, класс)467использовать, например, класс). Первый аргумент, передаваемый функции,468это словарь, содержащий переменные окружения в стиле CGI, а469второй аргумент – вызываемый объект.470"""471from wsgiref.simple_server import make_server472473def hello_world_app(environ, start_response):474 status = "200 OK" # HTTP-статус475 headers = [("Content-type", "text/plain; charset=utf-8")] # HTTP-заголовки476 start_response(status, headers)477478 # Возвращаемый объект будет выведен479 return [b"Hello World"]480481with make_server("", 8000, hello_world_app) as httpd:482 print("Serving on port 8000...")483484 # Обслуживать до завершения процесса485 httpd.serve_forever()486```487488Пример WSGI-приложения, обслуживающего текущий каталог; принимает опциональные каталог и номер порта (по умолчанию: 8000) из командной строки:489490```python491"""492Небольшой веб-сервер на основе wsgiref. Принимает путь для раздачи и493необязательный номер порта (по умолчанию 8000), затем пытается раздавать файлы.494MIME-типы определяются по именам файлов, выдаются ошибки 404,495если файл не найден.496"""497import mimetypes498import os499import sys500from wsgiref import simple_server, util501502def app(environ, respond):503 # Получить имя файла и MIME-тип504 fn = os.path.join(path, environ["PATH_INFO"][1:])505 if "." not in fn.split(os.path.sep)[-1]:506 fn = os.path.join(fn, "index.html")507 mime_type = mimetypes.guess_type(fn)[0]508509 # Возвращает 200 OK, если файл существует, иначе 404 Not Found510 if os.path.exists(fn):511 respond("200 OK", [("Content-Type", mime_type)])512 return util.FileWrapper(open(fn, "rb"))513 else:514 respond("404 Not Found", [("Content-Type", "text/plain")])515 return [b"not found"]516517if __name__ == "__main__":518 # Получает путь и порт из аргументов командной строки519 path = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()520 port = int(sys.argv[2]) if len(sys.argv) > 2 else 8000521522 # Создаёт и запускает сервер до нажатия Ctrl+C523 httpd = simple_server.make_server("", port, app)524 print(f"Serving {path} on port {port}, control-C to stop")525 try:526 httpd.serve_forever()527 except KeyboardInterrupt:528 print("Shutting down.")529 httpd.server_close()530```531