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

wsgiref.md

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

1> **Источник:** https://python-all.ru/3.2/library/wsgiref.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 20.4. [`wsgiref`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref) – Утилиты WSGI и эталонная реализация89Интерфейс шлюза веб-сервера (WSGI) – это стандартный интерфейс между веб-сервером и веб-приложениями на Python. Наличие стандартного интерфейса упрощает использование приложения, поддерживающего WSGI, с различными веб-серверами.1011Только разработчики веб-серверов и фреймворков должны знать все тонкости и пограничные случаи дизайна WSGI. Чтобы установить WSGI-приложение или написать веб-приложение с помощью готового фреймворка, не нужно понимать каждую деталь WSGI.1213[`wsgiref`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref) – эталонная реализация спецификации WSGI, которую можно использовать для добавления поддержки WSGI в веб-сервер или фреймворк. Она предоставляет утилиты для работы с переменными окружения WSGI и заголовками ответов, базовые классы для реализации серверов WSGI, демонстрационный HTTP-сервер, обслуживающий WSGI-приложения, а также инструмент проверки, который проверяет соответствие серверов и приложений WSGI спецификации ([**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html)).1415См. [http://www.wsgi.org](https://python-all.ru/3.2/library/wsgiref.html) для получения дополнительной информации о WSGI, а также ссылки на руководства и другие ресурсы.1617## 20.4.1. [`wsgiref.util`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.util) – утилиты окружения WSGI1819Этот модуль предоставляет различные утилиты для работы с окружениями WSGI. Окружение WSGI – это словарь, содержащий переменные HTTP-запроса, как описано в [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html). Все функции, принимающие параметр *environ*, ожидают словарь, совместимый с WSGI; подробную спецификацию см. в [**PEP 3333**](https://python-all.ru/3.2/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» [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html). Если *include\_query* равно false, строка запроса не включается в результирующий URI.3031#### `wsgiref.util.application_uri(environ)`3233Похоже на [`request_uri()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.util.request_uri), за исключением того, что переменные `PATH_INFO` и `QUERY_STRING` игнорируются. Результат – базовый URI объекта приложения, к которому обращается запрос.3435#### `wsgiref.util.shift_path_info(environ)`3637Переносит одно имя из `PATH_INFO` в `SCRIPT_NAME` и возвращает это имя. Словарь *environ* *изменяется* на месте; используйте копию, если нужно сохранить исходные `PATH_INFO` или `SCRIPT_NAME` нетронутыми.3839Если в `PATH_INFO` не осталось сегментов пути, возвращается `None`.4041Обычно эта процедура используется для обработки каждой части пути URI запроса, например, для трактовки пути как последовательности ключей словаря. Эта процедура изменяет переданное окружение, чтобы сделать его подходящим для вызова другого WSGI-приложения, расположенного по целевому URI. Например, если есть WSGI-приложение по адресу `/foo`, а путь URI запроса – `/foo/bar/baz`, и WSGI-приложение по адресу `/foo` вызывает [`shift_path_info()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.util.shift_path_info), то оно получит строку «bar», а окружение будет обновлено для передачи WSGI-приложению по адресу `/foo/bar`. То есть `SCRIPT_NAME` изменится с `/foo` на `/foo/bar`, а `PATH_INFO` изменится с `/bar/baz` на `/baz`.4243Когда `PATH_INFO` содержит просто «/», эта процедура возвращает пустую строку и добавляет завершающий слеш к `SCRIPT_NAME`, хотя пустые сегменты пути обычно игнорируются, а `SCRIPT_NAME` обычно не заканчивается слешем. Это намеренное поведение, чтобы гарантировать, что приложение может отличить URI, оканчивающиеся на `/x`, от оканчивающихся на `/x/` при использовании этой процедуры для обхода объектов.4445#### `wsgiref.util.setup_testing_defaults(environ)`4647Обновляет *environ* простыми значениями по умолчанию для целей тестирования.4849Эта процедура добавляет различные параметры, требуемые WSGI, включая `HTTP_HOST`, `SERVER_NAME`, `SERVER_PORT`, `REQUEST_METHOD`, `SCRIPT_NAME`, `PATH_INFO` и все переменные [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html)-defined `wsgi.*`. Она предоставляет только значения по умолчанию и не заменяет существующие настройки этих переменных.5051Эта процедура предназначена для упрощения настройки фиктивных окружений в модульных тестах серверов и приложений WSGI. Её НЕ следует использовать в реальных серверах или приложениях WSGI, поскольку данные являются фиктивными!5253Пример использования:5455```python56from wsgiref.util import setup_testing_defaults57from wsgiref.simple_server import make_server5859# Относительно простое WSGI-приложение. Оно выведет60# словарь окружения после обновления с помощью setup_testing_defaults61def simple_app(environ, start_response):62    setup_testing_defaults(environ)6364    status = '200 OK'65    headers = [('Content-type', 'text/plain; charset=utf-8')]6667    start_response(status, headers)6869    ret = [("%s: %s\n" % (key, value)).encode("utf-8")70           for key, value in environ.items()]71    return ret7273httpd = make_server('', 8000, simple_app)74print("Serving on port 8000...")75httpd.serve_forever()76```7778В дополнение к функциям окружения, перечисленным выше, модуль [`wsgiref.util`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.util) также предоставляет следующие прочие утилиты:7980#### `wsgiref.util.is_hop_by_hop(header_name)`8182Возвращает true, если ‘header\_name’ является HTTP/1.1 “Hop-by-Hop” заголовком, как определено в [**RFC 2616**](https://python-all.ru/3.2/library/wsgiref.html).8384#### `class wsgiref.util.FileWrapper(filelike, blksize=8192)`8586Обёртка для преобразования объекта, подобного файлу, в [*итератор*](https://python-all.ru/3.2/glossary.html#term-iterator). Полученные объекты поддерживают оба стиля итерации: [`__getitem__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__getitem__) и [`__iter__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__iter__), для совместимости с Python 2.1 и Jython. При итерации необязательный параметр *blksize* будет многократно передаваться методу *filelike* `read()` для получения байтовых строк, которые будут возвращаться. Когда `read()` возвращает пустую байтовую строку, итерация завершается и не может быть возобновлена.8788Если *filelike* имеет метод `close()`, возвращаемый объект также будет иметь метод `close()`, и при вызове он будет вызывать метод *filelike* `close()`.8990Пример использования:9192```python93from io import StringIO94from wsgiref.util import FileWrapper9596# В качестве файлоподобного объекта используется буфер StringIO97filelike = StringIO("This is an example file-like object"*10)98wrapper = FileWrapper(filelike, blksize=5)99100for chunk in wrapper:101    print(chunk)102```103104## 20.4.2. [`wsgiref.headers`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.headers) – инструменты для заголовков ответа WSGI105106Этот модуль предоставляет один класс, [`Headers`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.headers.Headers), для удобного управления заголовками ответов WSGI с помощью интерфейса, подобного отображению.107108#### `class wsgiref.headers.Headers(headers)`109110Создаёт объект, подобный отображению, оборачивающий *headers*, который должен быть списком кортежей имя заголовка/значение, как описано в [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html).111112Объекты [`Headers`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.headers.Headers) поддерживают типичные операции отображения, включая [`__getitem__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__getitem__), `get()`, [`__setitem__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__setitem__), `setdefault()`, [`__delitem__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__delitem__) и [`__contains__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__contains__). Для каждого из этих методов ключом является имя заголовка (регистронезависимое), а значением – первое значение, связанное с этим именем заголовка. Установка заголовка удаляет все существующие значения для этого заголовка, затем добавляет новое значение в конец обёрнутого списка заголовков. Существующий порядок заголовков в целом сохраняется, новые заголовки добавляются в конец обёрнутого списка.113114В отличие от словаря, объекты [`Headers`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.headers.Headers) не вызывают ошибку при попытке получить или удалить ключ, которого нет в обёрнутом списке заголовков. Получение несуществующего заголовка просто возвращает `None`, а удаление несуществующего заголовка ничего не делает.115116Объекты [`Headers`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.headers.Headers) также поддерживают методы `keys()`, `values()` и `items()`. Списки, возвращаемые `keys()` и `items()`, могут включать один и тот же ключ несколько раз, если есть заголовок с несколькими значениями. Длина `len()` объекта [`Headers`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.headers.Headers) равна длине его `items()`, что совпадает с длиной обёрнутого списка заголовков. Фактически, метод `items()` просто возвращает копию обёрнутого списка заголовков.117118Вызов `bytes()` для объекта [`Headers`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.headers.Headers) возвращает отформатированную байтовую строку, подходящую для передачи в качестве заголовков HTTP-ответа. Каждый заголовок размещается на строке со своим значением, разделёнными двоеточием и пробелом. Каждая строка завершается символами возврата каретки и перевода строки, а байтовая строка завершается пустой строкой.119120В дополнение к интерфейсу отображения и возможностям форматирования, объекты [`Headers`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.headers.Headers) также имеют следующие методы для запроса и добавления многозначных заголовков, а также для добавления заголовков с MIME-параметрами:121122#### `get_all(name)`123124Возвращает список всех значений для указанного заголовка.125126Возвращаемый список будет отсортирован в порядке появления в исходном списке заголовков или добавления в данный экземпляр, и может содержать дубликаты. Любые удалённые и повторно вставленные поля всегда добавляются в конец списка заголовков. Если полей с указанным именем не существует, возвращается пустой список.127128#### `add_header(name, value, **_params)`129130Добавляет (возможно, многозначный) заголовок с необязательными MIME-параметрами, задаваемыми через именованные аргументы.131132*name* – это добавляемое поле заголовка. Именованные аргументы можно использовать для задания MIME-параметров поля заголовка. Каждый параметр должен быть строкой или `None`. Подчёркивания в именах параметров заменяются на дефисы, так как дефисы недопустимы в идентификаторах Python, но многие имена MIME-параметров содержат дефисы. Если значение параметра – строка, оно добавляется к параметрам значения заголовка в виде `name="value"`. Если это `None`, добавляется только имя параметра. (Используется для MIME-параметров без значения.) Пример использования:133134```python135h.add_header('content-disposition', 'attachment', filename='bud.gif')136```137138Приведённый выше код добавит заголовок, который будет выглядеть так:139140```python141Content-Disposition: attachment; filename="bud.gif"142```143144## 20.4.3. [`wsgiref.simple_server`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.simple_server) – простой HTTP-сервер WSGI145146Этот модуль реализует простой HTTP-сервер (на основе [`http.server`](https://python-all.ru/3.2/library/http.server.html#module-http.server)), обслуживающий WSGI-приложения. Каждый экземпляр сервера обслуживает одно WSGI-приложение на заданном хосте и порту. Если требуется обслуживать несколько приложений на одном хосте и порту, следует создать WSGI-приложение, которое анализирует `PATH_INFO` для выбора, какое приложение вызывать для каждого запроса. (Например, с помощью функции `shift_path_info()` из [`wsgiref.util`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.util).)147148#### `wsgiref.simple_server.make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler)`149150Создаёт новый WSGI-сервер, прослушивающий *host* и *port*, принимающий соединения для *app*. Возвращаемое значение – экземпляр указанного *server\_class*, который будет обрабатывать запросы с помощью заданного *handler\_class*. *app* должен быть объектом WSGI-приложения, как определено в [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html).151152Пример использования:153154```python155from wsgiref.simple_server import make_server, demo_app156157httpd = make_server('', 8000, demo_app)158print("Serving HTTP on port 8000...")159160# Отвечать на запросы до завершения процесса161httpd.serve_forever()162163# Альтернатива: обработать один запрос и завершить работу164httpd.handle_request()165```166167#### `wsgiref.simple_server.demo_app(environ, start_response)`168169Эта функция представляет собой небольшое, но полноценное WSGI-приложение, которое возвращает текстовую страницу с сообщением «Hello world!» и списком пар ключ/значение, переданных в параметре *environ*. Она полезна для проверки того, что WSGI-сервер (например, [`wsgiref.simple_server`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.simple_server)) способен корректно запустить простое WSGI-приложение.170171#### `class wsgiref.simple_server.WSGIServer(server_address, RequestHandlerClass)`172173Создаёт экземпляр [`WSGIServer`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.WSGIServer). Параметр *server\_address* должен быть кортежем `(host,port)`, а *RequestHandlerClass* – подклассом [`http.server.BaseHTTPRequestHandler`](https://python-all.ru/3.2/library/http.server.html#http.server.BaseHTTPRequestHandler), который будет использоваться для обработки запросов.174175Обычно нет необходимости вызывать этот конструктор напрямую, так как функция [`make_server()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.make_server) может обработать все детали за вас.176177[`WSGIServer`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.WSGIServer) является подклассом [`http.server.HTTPServer`](https://python-all.ru/3.2/library/http.server.html#http.server.HTTPServer), поэтому все его методы (такие как `serve_forever()` и `handle_request()`) доступны. [`WSGIServer`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.WSGIServer) также предоставляет следующие WSGI-специфичные методы:178179#### `set_app(application)`180181Устанавливает вызываемый объект *application* в качестве WSGI-приложения, которое будет получать запросы.182183#### `get_app()`184185Возвращает установленный в данный момент вызываемый объект приложения.186187Однако обычно нет необходимости использовать эти дополнительные методы, так как [`set_app()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.WSGIServer.set_app) обычно вызывается функцией [`make_server()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.make_server), а [`get_app()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.WSGIServer.get_app) существует в основном для удобства экземпляров обработчиков запросов.188189#### `class wsgiref.simple_server.WSGIRequestHandler(request, client_address, server)`190191Создаёт HTTP-обработчик для заданных *request* (т.е. сокета), *client\_address* (кортеж `(host,port)`) и *server* (экземпляр [`WSGIServer`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.WSGIServer)).192193Нет необходимости создавать экземпляры этого класса напрямую; они автоматически создаются по мере необходимости объектами [`WSGIServer`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.WSGIServer). Однако можно создать подкласс этого класса и передать его в качестве *handler\_class* функции [`make_server()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.make_server). Некоторые методы, которые можно переопределить в подклассах:194195#### `get_environ()`196197Возвращает словарь, содержащий WSGI-окружение для запроса. Реализация по умолчанию копирует содержимое атрибута-словаря `base_environ` объекта [`WSGIServer`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.simple_server.WSGIServer), а затем добавляет различные заголовки, извлечённые из HTTP-запроса. Каждый вызов этого метода должен возвращать новый словарь, содержащий все соответствующие переменные CGI-окружения, как указано в [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html).198199#### `get_stderr()`200201Возвращает объект, который должен использоваться в качестве потока `wsgi.errors`. Реализация по умолчанию просто возвращает `sys.stderr`.202203#### `handle()`204205Обрабатывает HTTP-запрос. Реализация по умолчанию создаёт экземпляр обработчика, используя класс [`wsgiref.handlers`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.handlers) для реализации фактического интерфейса WSGI-приложения.206207## 20.4.4. [`wsgiref.validate`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.validate) – средство проверки соответствия WSGI208209При создании новых WSGI-приложений, фреймворков, серверов или промежуточного ПО может быть полезно проверить соответствие нового кода с помощью [`wsgiref.validate`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.validate). Этот модуль предоставляет функцию, которая создаёт WSGI-приложения, проверяющие взаимодействие между WSGI-сервером или шлюзом и объектом WSGI-приложения, чтобы обе стороны соблюдали протокол.210211Обратите внимание, что эта утилита не гарантирует полного соответствия [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html); отсутствие ошибок от этого модуля не обязательно означает, что ошибок не существует. Однако если этот модуль выдаёт ошибку, то практически наверняка либо сервер, либо приложение не соответствует требованиям на 100%.212213Этот модуль основан на модуле `paste.lint` из библиотеки Ian Bicking’s «Python Paste».214215#### `wsgiref.validate.validator(application)`216217Обёртывает *application* и возвращает новый объект WSGI-приложения. Возвращённое приложение будет перенаправлять все запросы исходному *application* и будет проверять, что и *application*, и вызывающий его сервер соответствуют спецификации WSGI и RFC 2616.218219Любое обнаруженное несоответствие приводит к возбуждению исключения [`AssertionError`](https://python-all.ru/3.2/library/exceptions.html#AssertionError); однако обработка этих ошибок зависит от сервера. Например, [`wsgiref.simple_server`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.simple_server) и другие серверы на основе [`wsgiref.handlers`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.handlers) (которые не переопределяют методы обработки ошибок для выполнения других действий) просто выводят сообщение о возникновении ошибки и печатают трассировку в `sys.stderr` или другой поток ошибок.220221This wrapper may also generate output using the [`warnings`](https://python-all.ru/3.2/library/warnings.html#module-warnings) module to indicate behaviors that are questionable but which may not actually be prohibited by [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html). Unless they are suppressed using Python command-line options or the [`warnings`](https://python-all.ru/3.2/library/warnings.html#module-warnings) API, any such warnings will be written to `sys.stderr` (*not* `wsgi.errors`, unless they happen to be the same object).222223Пример использования:224225```python226from wsgiref.validate import validator227from wsgiref.simple_server import make_server228229# Наш вызываемый объект, который намеренно не соответствует230# стандарту, поэтому валидатор выдаст ошибку231def simple_app(environ, start_response):232    status = '200 OK' # HTTP-статус233    headers = [('Content-type', 'text/plain')] # HTTP-заголовки234    start_response(status, headers)235236    # Это приведёт к ошибке, потому что нужно вернуть список, и237    # валидатор сообщит об этом238    return b"Hello World"239240# Это приложение, обёрнутое в валидатор241validator_app = validator(simple_app)242243httpd = make_server('', 8000, validator_app)244print("Listening on port 8000....")245httpd.serve_forever()246```247248## 20.4.5. [`wsgiref.handlers`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.handlers) – базовые классы сервера/шлюза249250Этот модуль предоставляет базовые классы обработчиков для реализации WSGI-серверов и шлюзов. Эти базовые классы берут на себя большую часть работы по взаимодействию с WSGI-приложением при условии, что им предоставлено окружение, подобное CGI, а также потоки ввода, вывода и ошибок.251252#### `class wsgiref.handlers.CGIHandler`253254Вызов на основе CGI через `sys.stdin`, `sys.stdout`, `sys.stderr` и `os.environ`. Это полезно, если есть WSGI-приложение, которое нужно запустить как CGI-скрипт. Просто вызовите `CGIHandler().run(app)`, где `app` – объект WSGI-приложения, которое требуется запустить.255256Этот класс является подклассом [`BaseCGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler), который устанавливает `wsgi.run_once` в true, `wsgi.multithread` в false и `wsgi.multiprocess` в true, а также всегда использует [`sys`](https://python-all.ru/3.2/library/sys.html#module-sys) и [`os`](https://python-all.ru/3.2/library/os.html#module-os) для получения необходимых CGI-потоков и окружения.257258#### `class wsgiref.handlers.IISCGIHandler`259260Специализированная альтернатива [`CGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.CGIHandler), предназначенная для использования при развёртывании на веб-сервере Microsoft IIS, без необходимости устанавливать опцию конфигурации allowPathInfo (IIS\>=7) или metabase allowPathInfoForScriptMappings (IIS\<7).261262По умолчанию IIS возвращает `PATH_INFO`, который дублирует `SCRIPT_NAME` в начале, что вызывает проблемы для WSGI-приложений, желающих реализовать маршрутизацию. Этот обработчик удаляет любой такой дублированный путь.263264IIS можно настроить на передачу правильного `PATH_INFO`, но это вызывает другую ошибку: `PATH_TRANSLATED` становится неверным. К счастью, эта переменная редко используется и не гарантируется WSGI. Однако на IIS\<7 настройку можно изменить только на уровне виртуального хоста, что затрагивает все остальные сопоставления скриптов, многие из которых ломаются при воздействии ошибки `PATH_TRANSLATED`. По этой причине IIS\<7 почти никогда не развёртывается с исправлением. (Даже IIS7 редко его использует, потому что для него всё ещё нет UI.)265266У CGI-кода нет способа определить, была ли установлена эта опция, поэтому предоставляется отдельный класс-обработчик. Он используется так же, как [`CGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.CGIHandler), то есть вызовом `IISCGIHandler().run(app)`, где `app` – это объект WSGI-приложения, которое требуется запустить.267268Новое в версии 3.2.269270#### `class wsgiref.handlers.BaseCGIHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)`271272Похож на [`CGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.CGIHandler), но вместо использования модулей [`sys`](https://python-all.ru/3.2/library/sys.html#module-sys) и [`os`](https://python-all.ru/3.2/library/os.html#module-os), CGI-окружение и потоки ввода-вывода задаются явно. Значения *multithread* и *multiprocess* используются для установки флагов `wsgi.multithread` и `wsgi.multiprocess` для любых приложений, запускаемых экземпляром обработчика.273274Этот класс является подклассом [`SimpleHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.SimpleHandler), предназначенным для использования с программным обеспечением, отличным от исходных HTTP-серверов. Если вы пишете реализацию шлюзового протокола (такого как CGI, FastCGI, SCGI и т.д.), который использует заголовок `Status:` для отправки HTTP-статуса, вероятно, вам нужно создать подкласс этого класса вместо [`SimpleHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.SimpleHandler).275276#### `class wsgiref.handlers.SimpleHandler(stdin, stdout, stderr, environ, multithread=True, multiprocess=False)`277278Похож на [`BaseCGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler), но предназначен для использования с исходными HTTP-серверами. Если разрабатывается реализация HTTP-сервера, вероятно, следует создать подкласс на основе этого, а не [`BaseCGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler)279280Этот класс является подклассом [`BaseHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler). Он переопределяет методы [`__init__()`](https://python-all.ru/3.2/reference/datamodel.html#object.__init__), `get_stdin()`, `get_stderr()`, `add_cgi_vars()`, `_write()` и `_flush()`, чтобы поддерживать явное задание окружения и потоков через конструктор. Предоставленные окружение и потоки сохраняются в атрибутах `stdin`, `stdout`, `stderr` и `environ`.281282#### `class wsgiref.handlers.BaseHandler`283284Это абстрактный базовый класс для запуска WSGI-приложений. Каждый экземпляр будет обрабатывать один HTTP-запрос, хотя в принципе можно создать подкласс, пригодный для повторного использования для нескольких запросов.285286Экземпляры [`BaseHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler) имеют только один метод, предназначенный для внешнего использования:287288#### `run(app)`289290Запускает указанное WSGI-приложение *app*.291292Все остальные методы [`BaseHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler) вызываются этим методом в процессе выполнения приложения и существуют в основном для того, чтобы позволить настраивать процесс.293294Следующие методы ОБЯЗАТЕЛЬНО должны быть переопределены в подклассе:295296#### `_write(data)`297298Буферизует байты *data* для передачи клиенту. Ничего страшного, если этот метод фактически передаёт данные; [`BaseHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler) просто разделяет операции записи и сброса для повышения эффективности, когда базовая система действительно имеет такое различие.299300#### `_flush()`301302Принудительно отправляет буферизованные данные клиенту. Ничего страшного, если этот метод ничего не делает (то есть если [`_write()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler._write) фактически отправляет данные).303304#### `get_stdin()`305306Возвращает объект входного потока, пригодный для использования в качестве `wsgi.input` текущего обрабатываемого запроса.307308#### `get_stderr()`309310Возвращает объект выходного потока, пригодный для использования в качестве `wsgi.errors` текущего обрабатываемого запроса.311312#### `add_cgi_vars()`313314Вставляет CGI-переменные для текущего запроса в атрибут `environ`.315316Вот некоторые другие методы и атрибуты, которые вы можете захотеть переопределить. Однако этот список является лишь кратким обзором и не включает каждый метод, который можно переопределить. Перед попыткой создать собственный подкласс [`BaseHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler) следует обратиться к строкам документации и исходному коду за дополнительной информацией.317318Атрибуты и методы для настройки окружения WSGI:319320#### `wsgi_multithread`321322Значение, используемое для переменной окружения `wsgi.multithread`. По умолчанию оно равно true в [`BaseHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler), но может иметь другое значение по умолчанию (или устанавливаться конструктором) в других подклассах.323324#### `wsgi_multiprocess`325326Значение, используемое для переменной окружения `wsgi.multiprocess`. По умолчанию оно равно true в [`BaseHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler), но может иметь другое значение по умолчанию (или устанавливаться конструктором) в других подклассах.327328#### `wsgi_run_once`329330Значение, которое будет использоваться для переменной окружения `wsgi.run_once`. По умолчанию оно равно false в [`BaseHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler), но [`CGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.CGIHandler) по умолчанию устанавливает его в true.331332#### `os_environ`333334Переменные окружения по умолчанию, которые будут включены в WSGI-окружение каждого запроса. По умолчанию это копия `os.environ` на момент импорта [`wsgiref.handlers`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.handlers), но подклассы могут создавать собственные на уровне класса или экземпляра. Обратите внимание, что словарь следует считать доступным только для чтения, так как значение по умолчанию разделяется между несколькими классами и экземплярами.335336#### `server_software`337338Если установлен атрибут [`origin_server`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server), значение этого атрибута используется для установки переменной окружения WSGI по умолчанию `SERVER_SOFTWARE`, а также для установки заголовка `Server:` по умолчанию в HTTP-ответах. Он игнорируется для обработчиков (таких как [`BaseCGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler) и [`CGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.CGIHandler)), которые не являются исходными HTTP-серверами.339340#### `get_scheme()`341342Возвращает схему URL, используемую для текущего запроса. Реализация по умолчанию использует функцию `guess_scheme()` из [`wsgiref.util`](https://python-all.ru/3.2/library/wsgiref.html#module-wsgiref.util), чтобы определить, должна ли схема быть «http» или «https», на основе переменных `environ` текущего запроса.343344#### `setup_environ()`345346Устанавливает атрибут `environ` в полностью заполненное WSGI-окружение. Реализация по умолчанию использует все вышеперечисленные методы и атрибуты, а также методы [`get_stdin()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stdin), [`get_stderr()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.get_stderr) и [`add_cgi_vars()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.add_cgi_vars) и атрибут [`wsgi_file_wrapper`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.wsgi_file_wrapper). Она также вставляет ключ `SERVER_SOFTWARE`, если он отсутствует, при условии, что атрибут [`origin_server`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server) является истинным, а атрибут [`server_software`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.server_software) установлен.347348Методы и атрибуты для настройки обработки исключений:349350#### `log_exception(exc_info)`351352Записывает кортеж *exc\_info* в журнал сервера. *exc\_info* – это кортеж вида `(type, value, traceback)`. Реализация по умолчанию просто записывает трассировку в поток `wsgi.errors` запроса и сбрасывает его. Подклассы могут переопределить этот метод, чтобы изменить формат или перенаправить вывод, отправить трассировку администратору по электронной почте или выполнить любое другое действие, которое сочтут подходящим.353354#### `traceback_limit`355356Максимальное количество кадров, включаемых в трассировки, выводимые методом [`log_exception()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.log_exception) по умолчанию. Если `None`, включаются все кадры.357358#### `error_output(environ, start_response)`359360Этот метод представляет собой WSGI-приложение для генерации страницы ошибки для пользователя. Он вызывается только в том случае, если ошибка возникает до отправки заголовков клиенту.361362Этот метод может получить текущую информацию об ошибке с помощью `sys.exc_info()` и должен передать эту информацию в *start\_response* при его вызове (как описано в разделе «Обработка ошибок» [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html)).363364Реализация по умолчанию просто использует атрибуты [`error_status`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_status), [`error_headers`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_headers) и [`error_body`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.error_body) для генерации выходной страницы. Подклассы могут переопределить это, чтобы создавать более динамичный вывод ошибок.365366Однако с точки зрения безопасности не рекомендуется выводить диагностическую информацию любому пользователю; в идеале необходимо выполнить специальные действия для включения диагностического вывода, поэтому в реализации по умолчанию он отсутствует.367368#### `error_status`369370HTTP-статус, используемый для ответов об ошибках. Это должна быть строка статуса, как определено в [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html); по умолчанию это код 500 и соответствующее сообщение.371372#### `error_headers`373374Заголовки HTTP, используемые для ответов об ошибках. Это должен быть список кортежей заголовков ответа WSGI (`(name, value)`), как описано в [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html). Список по умолчанию просто устанавливает тип содержимого в `text/plain`.375376#### `error_body`377378Тело ответа об ошибке. Это должна быть байтовая строка тела HTTP-ответа. По умолчанию это обычный текст: «A server error occurred. Please contact the administrator.»379380Methods and attributes for [**PEP 3333**](https://python-all.ru/3.2/library/wsgiref.html)‘s “Optional Platform-Specific File Handling” feature:381382#### `wsgi_file_wrapper`383384Фабрика `wsgi.file_wrapper` или `None`. Значением этого атрибута по умолчанию является класс [`wsgiref.util.FileWrapper`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.util.FileWrapper).385386#### `sendfile()`387388Переопределите для реализации передачи файлов, специфичной для платформы. Этот метод вызывается только в том случае, если возвращаемое значение приложения является экземпляром класса, указанного атрибутом [`wsgi_file_wrapper`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.wsgi_file_wrapper). Он должен вернуть истинное значение, если файл удалось успешно передать, чтобы код передачи по умолчанию не выполнялся. Реализация по умолчанию этого метода просто возвращает ложное значение.389390Разные методы и атрибуты:391392#### `origin_server`393394Этот атрибут должен быть установлен в истинное значение, если методы [`_write()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler._write) и [`_flush()`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler._flush) обработчика используются для прямой связи с клиентом, а не через шлюзовой протокол, подобный CGI, который ожидает HTTP-статус в специальном заголовке `Status:`.395396Значение этого атрибута по умолчанию равно true в [`BaseHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler), но false в [`BaseCGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseCGIHandler) и [`CGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.CGIHandler).397398#### `http_version`399400Если [`origin_server`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.BaseHandler.origin_server) истинно, этот строковый атрибут используется для установки версии HTTP ответа, отправляемого клиенту. По умолчанию он равен `"1.0"`.401402#### `wsgiref.handlers.read_environ()`403404Перекодирует переменные CGI из `os.environ` в строки PEP 3333 «bytes in unicode»\\nи возвращает новый словарь. Эта функция используется [`CGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.CGIHandler) и [`IISCGIHandler`](https://python-all.ru/3.2/library/wsgiref.html#wsgiref.handlers.IISCGIHandler) вместо прямого использования\\n`os.environ`, который не обязательно совместим с WSGI на всех платформах\\nи веб-серверах, использующих Python 3 – в частности, на тех, где\\nреальное окружение ОС в Unicode (т.е. Windows), или где окружение\\nв байтах, но системная кодировка, используемая Python для его декодирования, отлична\\nот ISO-8859-1 (например, Unix-системы с UTF-8).405406Если вы реализуете собственный CGI-обработчик, вероятно, вы захотите\\nиспользовать эту процедуру вместо того, чтобы просто копировать значения из\\n`os.environ` напрямую.407408Новое в версии 3.2.409410## 20.4.6. Примеры411412Это рабочее WSGI-приложение «Hello World»:413414```python415from wsgiref.simple_server import make_server416417# Каждое WSGI-приложение должно иметь объект приложения – вызываемый418# объект, который принимает два аргумента. Для этого419# можно использовать функцию (обратите внимание: можно не только функцию, но и, например, класс)420# использовать, например, класс). Первый аргумент, передаваемый функции,421# является словарём, содержащим переменные окружения в стиле CGI и422# вторая переменная – это вызываемый объект (см. PEP 333).423def hello_world_app(environ, start_response):424    status = '200 OK' # HTTP-статус425    headers = [('Content-type', 'text/plain; charset=utf-8')] # HTTP-заголовки426    start_response(status, headers)427428    # Возвращаемый объект будет выведен429    return [b"Hello World"]430431httpd = make_server('', 8000, hello_world_app)432print("Serving on port 8000...")433434# Обслуживать до завершения процесса435httpd.serve_forever()436```437