http.server — HTTP-серверы

Источник: Lib/http/server.py


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

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

http.server не рекомендуется для использования в производстве. Он реализует только basic security checks.

Availability: не WASI.

Этот модуль не работает или недоступен на WebAssembly. Дополнительную информацию см. в разделе Платформы WebAssembly.

Один класс, 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 будет ждать бесконечно долго.

Added in version 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

Содержит путь запроса. Если в URL присутствует компонент query, то path включает запрос. Используя терминологию RFC 3986, path здесь включает hier-part и query.

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

Указывает версию программного обеспечения сервера. Вы можете захотеть переопределить это значение. Формат - несколько строк, разделенных пробелами, где каждая строка имеет вид name[/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.

Added in version 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-сообщение, соответствующее коду ответа.

Added in version 3.2.

end_headers()

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

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

flush_headers()

Наконец, отправьте заголовки в выходной поток и промойте внутренний буфер заголовков.

Added in version 3.3.

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

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

log_error(...)

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

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)

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

Изменено в версии 3.7: Добавлен параметр directory.

Изменено в версии 3.9: Параметр directory принимает значение path-like object.

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

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

server_version

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

extensions_map

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

Изменено в версии 3.9: Этот словарь больше не заполнен системными отображениями по умолчанию, а содержит только переопределения.

Класс 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 в Lib/http/server.py.

Изменено в версии 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()

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

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

python -m http.server

По умолчанию сервер прослушивает порт 8000. Значение по умолчанию можно отменить, передав в качестве аргумента нужный номер порта:

python -m http.server 9000

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

python -m http.server --bind 127.0.0.1

Изменено в версии 3.4: Добавлена опция --bind.

Изменено в версии 3.8: Поддержка IPv6 в опции --bind.

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

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

Изменено в версии 3.7: Добавлена опция --directory.

По умолчанию сервер соответствует HTTP/1.0. Опция -p/--protocol задает версию HTTP, которой соответствует сервер. Например, следующая команда запускает сервер, соответствующий HTTP/1.1:

python -m http.server --protocol HTTP/1.1

Изменено в версии 3.11: Добавлена опция --protocol.

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-скриптов. Ошибка 501, «Can only POST to CGI scripts», выдается при попытке POST к не CGI url.

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

Утратил актуальность с версии 3.13, будет удален в версии 3.15: CGIHTTPRequestHandler будет удален в версии 3.15. CGI уже более десяти лет не считается хорошим способом выполнения задач. Этот код уже давно не поддерживается и практически не используется. Его сохранение может привести к дальнейшему security considerations.

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

python -m http.server --cgi

Утратил актуальность с версии 3.13, будет удален в версии 3.15: Поддержка http.server командной строки --cgi удаляется, потому что удаляется CGIHTTPRequestHandler.

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

CGIHTTPRequestHandler и опция командной строки --cgi не предназначены для использования недоверенными клиентами и могут быть уязвимы для эксплуатации. Всегда используйте их в безопасной среде.

Соображения безопасности

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

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

Изменено в версии 3.12: Управляющие символы затираются в журналах stderr.