> **Источник:** https://python-all.ru/3.1/library/http.server.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 20.20. `http.server` – HTTP-серверы

Этот модуль определяет классы для реализации HTTP-серверов (веб-серверов).

Один класс, [`HTTPServer`](https://python-all.ru/3.1/library/http.server.html#http.server.HTTPServer), является подклассом `socketserver.TCPServer`. Он создаёт HTTP-сокет и прослушивает его, направляя запросы обработчику. Код для создания и запуска сервера выглядит так:

```python
def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
    server_address = ('', 8000)
    httpd = server_class(server_address, handler_class)
    httpd.serve_forever()
```

#### `class http.server.HTTPServer(server_address, RequestHandlerClass)`

Этот класс расширяет класс

`TCPServer`

, сохраняя адрес сервера в переменных экземпляра с именами

`server_name`

и

`server_port`

. Сервер доступен обработчику, обычно через переменную экземпляра

`server`

обработчика.

При создании экземпляра [`HTTPServer`](https://python-all.ru/3.1/library/http.server.html#http.server.HTTPServer) необходимо передать *RequestHandlerClass*, для которого этот модуль предоставляет три различных варианта:

#### `class http.server.BaseHTTPRequestHandler(request, client_address, server)`

Этот класс используется для обработки HTTP-запросов, поступающих на сервер. Сам по себе он не может отвечать на реальные HTTP-запросы; его нужно наследовать, чтобы обрабатывать каждый метод запроса (например, GET или POST). [`BaseHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler) предоставляет ряд переменных класса и экземпляра, а также методы для использования подклассами.

Обработчик разбирает запрос и заголовки, затем вызывает метод, соответствующий типу запроса. Имя метода формируется из запроса. Например, для метода запроса `SPAM` будет вызван метод `do_SPAM()` без аргументов. Вся соответствующая информация хранится в переменных экземпляра обработчика. Подклассы не должны переопределять или расширять метод [`__init__()`](https://python-all.ru/3.1/reference/datamodel.html#object.__init__).

[`BaseHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler) имеет следующие переменные экземпляра:

#### `client_address`

Содержит кортеж вида

`(host, port)`

, относящийся к адресу клиента.

#### `server`

Содержит экземпляр сервера.

#### `command`

Содержит команду (тип запроса). Например,

`'GET'`

.

#### `path`

Содержит путь запроса.

#### `request_version`

Содержит строку версии из запроса. Например,

`'HTTP/1.0'`

.

#### `headers`

Содержит экземпляр класса, указанного

[`MessageClass`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.MessageClass)

переменной класса. Этот экземпляр разбирает и управляет заголовками в HTTP- запросе.

#### `rfile`

Содержит входной поток, находящийся в начале необязательных входных данных.

#### `wfile`

Содержит выходной поток для записи ответа обратно клиенту. При записи в этот поток необходимо строго соблюдать протокол HTTP.

[`BaseHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler) имеет следующие переменные класса:

#### `server_version`

Указывает версию серверного программного обеспечения. Возможно, потребуется переопределить это значение. Формат – несколько строк, разделённых пробелами, где каждая строка имеет вид имя\[/версия\]. Например,

`'BaseHTTP/0.2'`

.

#### `sys_version`

Содержит версию системы Python в форме, пригодной для использования методом

[`version_string`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.version_string)

и переменной класса

[`server_version`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.server_version)

. Например,

`'Python/1.4'`

.

#### `error_message_format`

Задает строку формата для построения ответа об ошибке клиенту. Она использует спецификаторы формата в круглых скобках с ключами, поэтому операнд формата должен быть словарем. Ключ

*code*

должен быть целым числом, указывающим числовое значение HTTP-кода ошибки.

*message*

должен быть строкой, содержащей (подробное) сообщение об ошибке о том, что произошло, а

*explain*

должен быть объяснением номера кода ошибки. Значения по умолчанию для

*message*

и

*explain*

можно найти в переменной класса

*responses*

.

#### `error_content_type`

Задаёт HTTP-заголовок Content-Type для ответов об ошибках, отправляемых клиенту. Значение по умолчанию:

`'text/html'`

.

#### `protocol_version`

Задаёт версию протокола HTTP, используемую в ответах. Если установлено

`'HTTP/1.1'`

, сервер будет разрешать постоянные соединения; однако в этом случае сервер

*должен*

включать точный заголовок

`Content-Length`

(с помощью

[`send_header()`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.send_header)

) во все свои ответы клиентам. Для обратной совместимости по умолчанию используется

`'HTTP/1.0'`

.

#### `MessageClass`

Задаёт класс, похожий на

[`email.message.Message`](https://python-all.ru/3.1/library/email.message.html#email.message.Message)

, для разбора HTTP-заголовков. Обычно его не переопределяют, и по умолчанию используется

`http.client.HTTPMessage`

.

#### `responses`

Эта переменная содержит отображение целочисленных кодов ошибок в кортежи из двух элементов, содержащие краткое и полное сообщения. Например,

`{code: (shortmessage, longmessage)}`

.

*shortmessage*

обычно используется как ключ

*message*

в ответе об ошибке, а

*longmessage*

– как ключ

*explain*

(см. переменную класса

[`error_message_format`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.error_message_format)

).

Экземпляр [`BaseHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler) имеет следующие методы:

#### `handle()`

Вызывает

[`handle_one_request()`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.handle_one_request)

один раз (или несколько, если включены постоянные соединения) для обработки входящих HTTP-запросов. Этот метод не нужно переопределять; вместо этого следует реализовать соответствующие методы

`do_*()`

.

#### `handle_one_request()`

Этот метод разбирает запрос и направляет его в соответствующий метод

`do_*()`

. Его не нужно переопределять.

#### `send_error(code, message=None)`

Отправляет и регистрирует полный ответ об ошибке клиенту. Числовой

*code*

задает HTTP-код ошибки, а

*message*

– необязательный, более конкретный текст. Отправляется полный набор заголовков, за которым следует текст, составленный с использованием переменной класса

[`error_message_format`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.error_message_format)

.

#### `send_response(code, message=None)`

Отправляет заголовок ответа и регистрирует принятый запрос. Отправляется строка состояния HTTP, за которой следуют заголовки

*Server*

и

*Date*

. Значения для этих двух заголовков берутся из методов

[`version_string()`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.version_string)

и

[`date_time_string()`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.date_time_string)

соответственно.

#### `send_header(keyword, value)`

Записывает указанный HTTP-заголовок в выходной поток.

*keyword*

задаёт ключевое слово заголовка, а

*value*

– его значение.

#### `end_headers()`

Отправляет пустую строку, сигнализирующую об окончании HTTP-заголовков в ответе.

#### `log_request(code='-', size='-')`

Записывает в журнал принятый (успешный) запрос. Параметр

*code*

должен задавать числовой код HTTP, связанный с ответом. Если размер ответа доступен, его следует передать как параметр

*size*

.

#### `log_error(...)`

Журналирует ошибку, если запрос не может быть выполнен. По умолчанию передаёт сообщение в

[`log_message()`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.log_message)

, поэтому принимает те же аргументы (

*format*

и дополнительные значения).

#### `log_message(format, ...)`

Записывает произвольное сообщение в

`sys.stderr`

. Обычно этот метод переопределяют для создания собственных механизмов журналирования ошибок. Аргумент

*format*

– это строка форматирования в стиле printf, в которую подставляются дополнительные аргументы

[`log_message()`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.log_message)

. К каждому сообщению добавляются адрес клиента и текущие дата и время.

#### `version_string()`

Возвращает строку версии серверного ПО. Она представляет собой комбинацию классовых переменных

[`server_version`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.server_version)

и

[`sys_version`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler.sys_version)

.

#### `date_time_string(timestamp=None)`

Возвращает дату и время, заданные *timestamp* (который должен быть None или в формате, возвращаемом [`time.time()`](https://python-all.ru/3.1/library/time.html#time.time)), отформатированные для заголовка сообщения. Если *timestamp* опущен, используются текущие дата и время.

Результат выглядит как `'Sun, 06 Nov 1994 08:49:37 GMT'`.

#### `log_date_time_string()`

Возвращает текущие дату и время, отформатированные для логирования.

#### `address_string()`

Возвращает адрес клиента, отформатированный для логирования. Для IP-адреса клиента выполняется поиск имени.

#### `class http.server.SimpleHTTPRequestHandler(request, client_address, server)`

Этот класс обслуживает файлы из текущего каталога и подкаталогов, напрямую отображая структуру каталогов на HTTP-запросы.

Большая часть работы, такая как разбор запроса, выполняется базовым классом [`BaseHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.BaseHTTPRequestHandler). Этот класс реализует функции [`do_GET()`](https://python-all.ru/3.1/library/http.server.html#http.server.SimpleHTTPRequestHandler.do_GET) и [`do_HEAD()`](https://python-all.ru/3.1/library/http.server.html#http.server.SimpleHTTPRequestHandler.do_HEAD).

Следующие атрибуты определены как атрибуты класса [`SimpleHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.SimpleHTTPRequestHandler):

#### `server_version`

Это будет

`"SimpleHTTP/" + __version__`

, где

`__version__`

определена на уровне модуля.

#### `extensions_map`

Словарь, сопоставляющий расширения с MIME-типами. Значение по умолчанию обозначается пустой строкой и считается равным

`application/octet-stream`

. Сопоставление используется без учёта регистра, поэтому должно содержать только ключи в нижнем регистре.

Класс [`SimpleHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.SimpleHTTPRequestHandler) определяет следующие методы:

#### `do_HEAD()`

This method serves the

`'HEAD'`

request type: it sends the headers it would send for the equivalent

`GET`

request. See the

[`do_GET()`](https://python-all.ru/3.1/library/http.server.html#http.server.SimpleHTTPRequestHandler.do_GET)

method for a more complete explanation of the possible headers.

#### `do_GET()`

Запрос сопоставляется с локальным файлом путём интерпретации запроса как пути относительно текущего рабочего каталога.

Если запрос был сопоставлен с каталогом, в этом каталоге проверяется наличие файла с именем `index.html` или `index.htm` (в указанном порядке). Если файл найден, возвращается его содержимое; в противном случае генерируется содержимое каталога вызовом метода `list_directory()`. Этот метод использует [`os.listdir()`](https://python-all.ru/3.1/library/os.html#os.listdir) для сканирования каталога и возвращает ответ с ошибкой `404`, если `listdir()` завершается неудачей.

Если запрос был сопоставлен с файлом, он открывается и возвращается его содержимое. Любое исключение [`IOError`](https://python-all.ru/3.1/library/exceptions.html#IOError) при открытии запрошенного файла преобразуется в ошибку `404`, `'File not found'`. В противном случае тип содержимого определяется вызовом метода `guess_type()`, который, в свою очередь, использует переменную *extensions\_map*.

Выводится заголовок `'Content-type:'` с определённым типом содержимого, затем заголовок `'Content-Length:'` с размером файла и заголовок `'Last-Modified:'` с временем изменения файла.

Затем идёт пустая строка, обозначающая конец заголовков, а затем выводится содержимое файла. Если MIME-тип файла начинается с `text/`, файл открывается в текстовом режиме; в противном случае используется двоичный режим.

Пример использования см. в реализации `test()` вызова функции в модуле `http.server`.

Класс [`SimpleHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.SimpleHTTPRequestHandler) можно использовать следующим образом для создания очень простого веб-сервера, раздающего файлы из текущего каталога.

```python
import http.server
import socketserver

PORT = 8000

Handler = http.server.SimpleHTTPRequestHandler

httpd = socketserver.TCPServer(("", PORT), Handler)

print("serving at port", PORT)
httpd.serve_forever()
```

`http.server` также может вызываться напрямую с помощью переключателя *-m* интерпретатора с аргументом `port number`. Подобно предыдущему примеру, он обслуживает файлы относительно текущего каталога.

```python
python -m http.server 8000
```

#### `class http.server.CGIHTTPRequestHandler(request, client_address, server)`

Этот класс используется для обслуживания файлов или вывода CGI-скриптов из текущего каталога и всех подкаталогов. Обратите внимание, что сопоставление иерархической структуры HTTP с локальной файловой структурой производится точно так же, как в [`SimpleHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.SimpleHTTPRequestHandler).

> **Примечание**
>
> CGI-скрипты, запускаемые классом [`CGIHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.CGIHTTPRequestHandler), не могут выполнять перенаправления (HTTP-код 302), поскольку код 200 (за которым следует вывод скрипта) отправляется до выполнения CGI-скрипта. Это заменяет код состояния.

Однако класс будет запускать CGI-скрипт вместо того, чтобы отдавать его как файл, если он определит, что это CGI-скрипт. Используются только каталогизированные CGI – другая распространённая конфигурация сервера (обработка специальных расширений как обозначающих CGI-скрипты) не применяется.

Функции `do_GET()` и `do_HEAD()` изменены для запуска CGI-скриптов и выдачи их результатов вместо файлов, если запрос ведёт к пути, расположенному внутри `cgi_directories`.

[`CGIHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.CGIHTTPRequestHandler) определяет следующий атрибут данных:

#### `cgi_directories`

По умолчанию это значение равно

`['/cgi-bin', '/htbin']`

и определяет каталоги, которые считаются содержащими CGI-скрипты.

[`CGIHTTPRequestHandler`](https://python-all.ru/3.1/library/http.server.html#http.server.CGIHTTPRequestHandler) определяет следующий метод:

#### `do_POST()`

Этот метод обрабатывает запросы типа

`'POST'`

, разрешённые только для CGI скриптов. При попытке отправить POST на не-CGI URL выводится ошибка 501 «Can only POST to CGI scripts».

Обратите внимание: из соображений безопасности CGI-скрипты будут запускаться с UID пользователя nobody. Проблемы с CGI-скриптом приведут к ошибке 403.
