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

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


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

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

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

Один класс, 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

Содержит путь запроса. Если в 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.

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

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

end_headers()

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

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

flush_headers()

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

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

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

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

log_error(...)

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

log_message(format, ...)

Записывает произвольное сообщение в журнал sys.stderr. Это обычно переопределяется для создания пользовательских механизмов регистрации ошибок. Аргумент формат представляет собой стандартную строку формата в стиле 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: Параметр директория.

Изменено в версии 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() в модуле 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 интерпретатора. Как и в предыдущем примере, при этом файлы обслуживаются относительно текущего каталога:

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: Аргумент --bind улучшен для поддержки IPv6

По умолчанию сервер использует текущий каталог. Опция -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-скриптов. Ошибка 501, «Can only POST to CGI scripts», выдается при попытке POST к не CGI url.

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

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

python -m http.server --cgi

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

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

Вернуться на верх