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

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

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


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

Предупреждение

http.server не рекомендуется для использования в продакшене. Он реализует только базовые проверки безопасности.

Один класс, 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 обработчика.

class http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)

Этот класс идентичен HTTPServer, но использует потоки для обработки запросов с помощью ThreadingMixIn. Это полезно для обработки ситуаций, когда веб-браузеры предварительно открывают сокеты, на которых HTTPServer будет ожидать бесконечно.

Добавлено в версии 3.7.

HTTPServer и ThreadingHTTPServer должны быть указаны при создании RequestHandlerClass, для которого этот модуль предоставляет три различных варианта:

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

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

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

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

client_address

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

server

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

close_connection

Логическое значение, которое следует установить до того, как handle_one_request() вернёт результат. Оно указывает, ожидается ли ещё один запрос или соединение следует закрыть.

requestline

Содержит строковое представление HTTP-строки запроса. Завершающий CRLF удаляется. Этот атрибут должен быть установлен handle_one_request(). Если ни одна допустимая строка запроса не была обработана, его следует установить в пустую строку.

command

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

path

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

request_version

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

headers

Содержит экземпляр класса, заданного переменной класса MessageClass. Этот экземпляр разбирает и управляет заголовками HTTP-запроса. Функция parse_headers() из http.client используется для разбора заголовков, и она требует, чтобы HTTP-запрос предоставлял корректный заголовок в стиле RFC 2822.

rfile

Входной поток io.BufferedIOBase, готовый к чтению с начала необязательных входных данных.

wfile

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

Изменено в версии 3.6: Это поток io.BufferedIOBase.

BaseHTTPRequestHandler имеет следующие атрибуты:

server_version

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

sys_version

Содержит версию системы Python в форме, пригодной для использования методом version_string и классовой переменной server_version. Например, 'Python/1.4'.

error_message_format

Задаёт строку формата, которая должна использоваться методом send_error() для формирования ответа об ошибке клиенту. Строка по умолчанию заполняется переменными из responses на основе кода состояния, переданного в send_error().

error_content_type

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

protocol_version

Определяет версию HTTP-протокола, используемую в ответах. Если установлено в 'HTTP/1.1', сервер будет разрешать постоянные HTTP-соединения; однако сервер должен затем включать точный заголовок Content-Length (используя send_header()) во все свои ответы клиентам. Для обратной совместимости по умолчанию используется 'HTTP/1.0'.

MessageClass

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

responses

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

Экземпляр 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, explain=None)

Отправляет и записывает в журнал полный ответ об ошибке клиенту. Числовой код code задаёт код HTTP-ошибки, а message – необязательное короткое, понятное человеку описание ошибки. Аргумент explain можно использовать для предоставления более подробной информации об ошибке; он будет отформатирован с использованием атрибута error_message_format и отправлен после полного набора заголовков в качестве тела ответа. Атрибут responses содержит значения по умолчанию для message и explain, которые будут использованы, если значение не указано; для неизвестных кодов значением по умолчанию для обоих является строка ???. Тело будет пустым, если метод HEAD или код ответа является одним из следующих: 1xx, 204 No Content, 205 Reset Content, 304 Not Modified.

Изменено в версии 3.4: Ответ об ошибке включает заголовок Content-Length. Добавлен аргумент explain.

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, directory=None)

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

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

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

server_version

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

extensions_map

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

directory

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

Класс SimpleHTTPRequestHandler определяет следующие методы:

do_HEAD()

Этот метод обслуживает тип запроса 'HEAD': он отправляет заголовки, которые отправил бы для эквивалентного запроса GET. Смотрите метод do_GET() для более полного объяснения возможных заголовков.

do_GET()

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

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

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

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

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

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

Изменено в версии 3.7: Поддержка заголовка 'If-Modified-Since'.

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

import http.server
import socketserver

PORT = 8000

Handler = http.server.SimpleHTTPRequestHandler

with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()

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

python -m http.server 8000

По умолчанию сервер привязывается ко всем интерфейсам. Опция -b/--bind\nуказывает конкретный адрес, к которому он должен привязываться. Например,\nследующая команда заставляет сервер привязываться только к localhost:

python -m http.server 8000 --bind 127.0.0.1

Новое в версии 3.4: Был введён аргумент --bind.

По умолчанию сервер использует текущий каталог. Параметр -d/--directory указывает каталог, из которого следует обслуживать файлы. Например, следующая команда использует конкретный каталог:

python -m http.server --directory /tmp/

Новое в версии 3.7: --directory указывает альтернативный каталог

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

Вопросы безопасностиSecurity Considerations

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

В более ранних версиях Python не удалялись управляющие символы из сообщений журнала, выводимых в stderr из python -m http.server или реализации по умолчанию BaseHTTPRequestHandler .log_message. Это могло позволить удалённым клиентам, подключающимся к вашему серверу, отправлять вредоносные управляющие коды на ваш терминал.

Новое в версии 3.7.16: очистка управляющих символов из сообщений журнала