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

21.22. http.server – HTTP-серверыhttp.server – HTTP servers

Исходный код: Lib/http/server.py


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

Один класс, HTTPServer, является подклассом socketserver.TCPServer. Он создаёт HTTP-сокет и прослушивает его, направляя запросы обработчику. Код для создания и запуска сервера выглядит так:

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 необходимо передать RequestHandlerClass, для которого этот модуль предоставляет три различных варианта:

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

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

Обработчик разбирает запрос и заголовки, затем вызывает метод, соответствующий типу запроса. Имя метода формируется из запроса. Например, для метода запроса SPAM будет вызван метод do_SPAM() без аргументов. Вся соответствующая информация хранится в переменных экземпляра обработчика. Подклассы не должны переопределять или расширять метод __init__().

BaseHTTPRequestHandler имеет следующие переменные экземпляра:

client_address

Содержит кортеж вида (host, port), относящийся к адресу клиента.

server

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

command

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

path

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

request_version

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

headers

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

rfile

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

wfile

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

BaseHTTPRequestHandler имеет следующие переменные класса:

server_version

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

sys_version

Содержит версию системы Python в форме, пригодной для использования методом version_string и переменной класса 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()) во все свои ответы клиентам. Для обратной совместимости по умолчанию используется 'HTTP/1.0'.

MessageClass

Задаёт класс, похожий на email.message.Message, для разбора HTTP-заголовков. Обычно его не переопределяют, и по умолчанию используется http.client.HTTPMessage.

responses

Эта переменная содержит отображение целочисленных кодов ошибок в кортежи из двух элементов, содержащие краткое и полное сообщения. Например, {code: (shortmessage, longmessage)}. shortmessage обычно используется как ключ message в ответе об ошибке, а longmessage – как ключ explain (см. переменную класса error_message_format).

Экземпляр BaseHTTPRequestHandler имеет следующие методы:

handle()

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

handle_one_request()

Этот метод разбирает запрос и направляет его в соответствующий метод do_*(). Его не нужно переопределять.

handle_expect_100()

Когда HTTP/1.1-совместимый сервер получает заголовок запроса Expect: 100-continue, он отвечает заголовками 100 Continue, за которыми следуют 200 OK. Этот метод можно переопределить, чтобы вызвать ошибку, если сервер не хочет, чтобы клиент продолжал. Например, сервер может решить отправить 417 Expectation Failed в качестве заголовка ответа и return False.

Новое в версии 3.2.

send_error(code, message=None)

Отправляет и регистрирует полный ответ об ошибке клиенту. Числовой code задает HTTP-код ошибки, а message – необязательный, более конкретный текст. Отправляется полный набор заголовков, за которым следует текст, составленный с использованием переменной класса error_message_format.

send_response(code, message=None)

Добавляет заголовок ответа в буфер заголовков и регистрирует принятый запрос. Строка HTTP-ответа записывается во внутренний буфер, за ней следуют заголовки Server и Date. Значения этих двух заголовков берутся из методов version_string() и date_time_string() соответственно. Если сервер не собирается отправлять другие заголовки с помощью метода send_header(), то за вызовом send_response() должен следовать вызов end_headers().

Изменено в версии 3.3: Заголовки сохраняются во внутренний буфер, и end_headers() требуется вызывать явно.

send_header(keyword, value)

Добавляет HTTP-заголовок во внутренний буфер, который будет записан в выходной поток при вызове end_headers() или flush_headers(). keyword задаёт ключевое слово заголовка, а value – его значение. Обратите внимание: после выполнения всех вызовов send_header end_headers() ДОЛЖЕН быть вызван для завершения операции.

Изменено в версии 3.2: Заголовки сохраняются во внутреннем буфере.

send_response_only(code, message=None)

Отправляет только заголовок ответа, используется для случаев, когда сервер отправляет клиенту ответ 100 Continue. Заголовки не буферизуются и отправляются непосредственно в выходной поток. Если message не указан, отправляется HTTP-сообщение, соответствующее коду ответа code.

Новое в версии 3.2.

end_headers()

Добавляет пустую строку (означающую конец HTTP-заголовков в ответе) в буфер заголовков и вызывает flush_headers().

Изменено в версии 3.2: Буферизированные заголовки записываются в выходной поток.

flush_headers()

Наконец отправляет заголовки в выходной поток и очищает внутренний буфер заголовков.

Новое в версии 3.3.

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

Записывает в журнал принятый (успешный) запрос. Параметр code должен задавать числовой код HTTP, связанный с ответом. Если размер ответа доступен, его следует передать как параметр size.

log_error(...)

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

log_message(format, ...)

Записывает произвольное сообщение в sys.stderr. Обычно этот метод переопределяют для создания собственных механизмов регистрации ошибок. Аргумент format – это стандартная printf-строка форматирования, к которой дополнительные аргументы log_message() применяются как входные данные для форматирования. IP-адрес клиента и текущие дата и время добавляются в начало каждого сообщения.

version_string()

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

date_time_string(timestamp=None)

Возвращает дату и время, заданные timestamp (который должен быть None или в формате, возвращаемом time.time()), отформатированные для заголовка сообщения. Если timestamp опущен, используются текущие дата и время.

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

log_date_time_string()

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

address_string()

Возвращает адрес клиента.

Изменено в версии 3.3: Ранее выполнялся поиск по имени. Чтобы избежать задержек разрешения имён, теперь всегда возвращается IP-адрес.

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

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

Большая часть работы, такая как разбор запроса, выполняется базовым классом BaseHTTPRequestHandler. Этот класс реализует функции do_GET() и do_HEAD().

Следующие атрибуты определены как атрибуты класса SimpleHTTPRequestHandler:

server_version

Это будет "SimpleHTTP/" + __version__, где __version__ определена на уровне модуля.

extensions_map

Словарь, сопоставляющий расширения с MIME-типами. Значение по умолчанию обозначается пустой строкой и считается равным application/octet-stream. Сопоставление используется без учёта регистра, поэтому должно содержать только ключи в нижнем регистре.

Класс 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() method for a more complete explanation of the possible headers.

do_GET()

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

Если запрос был сопоставлен с каталогом, то в нём ищется файл с именем index.html или index.htm (именно в таком порядке). Если файл найден, возвращается его содержимое; в противном случае формируется список содержимого каталога вызовом метода list_directory(). Этот метод использует os.listdir() для просмотра каталога и возвращает ответ с ошибкой 404, если listdir() завершается неудачей.

Если запрос был сопоставлен с файлом, он открывается и возвращается его содержимое. Любое исключение OSError при открытии запрошенного файла преобразуется в ошибку 404, 'File not found'. В противном случае тип содержимого определяется вызовом метода guess_type(), который, в свою очередь, использует переменную extensions_map.

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

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

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

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

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 -m http.server 8000
class http.server.CGIHTTPRequestHandler(request, client_address, server)

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

Примечание

CGI-скрипты, запускаемые классом CGIHTTPRequestHandler, не могут выполнять перенаправления (HTTP-код 302), поскольку код 200 (за которым следует вывод скрипта) отправляется до выполнения CGI-скрипта. Это заменяет код состояния.

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

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

CGIHTTPRequestHandler определяет следующий атрибут данных:

cgi_directories

По умолчанию это значение равно ['/cgi-bin', '/htbin'] и определяет каталоги, которые считаются содержащими CGI-скрипты.

CGIHTTPRequestHandler определяет следующий метод:

do_POST()

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

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

CGIHTTPRequestHandler можно включить в командной строке, передав параметр --cgi.:

python -m http.server --cgi 8000