Создание локального HTTP-сервера

Последнее обновление: 09.12.2025

В Python для этого есть встроенный модуль http.server, который позволяет развернуть сервер без установки сторонних библиотек (вроде Flask или Django). Этот модуль идеально подходит для таких задач, как:

  • Быстрого обмена файлами в локальной сети.

  • Тестирования простых HTML/JS страниц.

  • Создания "заглушек" (mock-серверов) для тестирования API.

  • Обучения основам HTTP-протокола.

В то же время стоит учитывать, http.server НЕ предназначен для полноценного использования в продакшене (Production) в виду некоторых ограничений безопасности.

Запуск из командной строки

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

python -m http.server [OPTIONS] [port]

Поэтому если цель http-сервера - просто "раздать" файлы из текущей папки, то достаточно открыть терминал и ввести:

python -m http.server

По умолчанию HTTP-сервер запускается по адресу http://127.0.0.1:8000/. И если мы откроем браузер и введем этот адрес, то увидим список файлов из папки, где была запущена команда.

eugene@Eugene:~/python/httpserver$ ls -l
total 5
-rwxrwxrwx 1 root root 1138 Nov 10 16:54 app.py
-rwxrwxrwx 1 root root  140 Aug 17 11:55 hello.txt
-rwxrwxrwx 1 root root  140 Aug 17 11:55 test.py

eugene@Eugene:~/python/httpserver$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [07/Dec/2025 22:22:49] "GET / HTTP/1.1" 200 -
HTTP-сервер на Python с помощью модуля http.server

Рассмотрим, какие параметры можно передать при запуске сервера:

  • port

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

    python -m http.server 9000
  • -b, --bind [адрес]

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

    python -m http.server --bind 127.0.0.1
    
  • -d, --directory [Каталог]

    Указывает на используемый каталог. По умолчанию сервер использует текущий каталог. Например, следующая команда использует определённый каталог:

    python -m http.server --directory /tmp/
    
  • -p, --protocol [версия]

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

    python -m http.server --protocol HTTP/1.1
    
  • --tls-cert

    Задаёт цепочку сертификатов TLS для HTTPS-подключений:

    python -m http.server --tls-cert fullchain.pem
    
  • --tls-key

    Задаёт файл закрытого ключа для HTTPS-подключений. Для этого параметра требуется указать --tls-cert.

  • --tls-password-file

    Задаёт файл паролей для закрытых ключей, защищённых паролем:

    python -m http.server \
    --tls-cert cert.pem \
    --tls-key key.pem \
    --tls-password-file password.txt

Создание кастомного сервера

Для программного создания HTTP-сервера в модуле http.server определены следующие классы:

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

  • ThreadingHTTPServer: идентичен HTTPServer, но использует потоки для обработки запросов

  • HTTPSServer: подкласс HTTPServer с использованием модуля ssl. Если модуль SSL недоступен, создание экземпляра объекта HTTPServer завершается с ошибкой RuntimeError.

  • ThreadingHTTPSServer: идентичен HTTPSServer, но использует потоки для обработки запросов аналогично ThreadingHTTPServer, только с использованием HTTPSServer.

При создании экземпляра этих классов в конструктор передается объект socketserver.StreamRequestHandler. В модуле http.server для определены три его подкласса:

  • BaseHTTPRequestHandler: используется для обработки HTTP-запросов, поступающих на сервер. Он также предоставляет ряд переменных класса и экземпляра, а также методов для использования подклассами.

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

  • CGIHTTPRequestHandler: используется для обслуживания файлов или вывода сценариев CGI из текущего каталога и ниже.

Возьмем самый простой класс - HTTPServer

class http.server.HTTPServer(server_address, RequestHandlerClass)

Этот класс HTTPServer наследуется от класса socketserver.TCPServer, который представляет функциональность tcp-сервера. Через первый параметр этот класс получает адрес сервера - собственно адрес и сетевой порт и сохраняет их в переменных server_name и server_port. Второй параметр - RequestHandlerClass представляет обработчик запросов - именно через него мы и определяем, что делать, если пришел запрос.

Рассмотрим самый простейший пример обработки запросов. Используем в качестве обработчика самый простой класс обработчика - BaseHTTPRequestHandler

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

Пусть наш веб-сервер просто будет отправлять некоторое сообщение в ответ. Для этого определим следующий скрипт:

from http.server import HTTPServer, BaseHTTPRequestHandler

# Класс-обработчик входящих запросов
class MyHandler(BaseHTTPRequestHandler):
    # обработка get-запросов
    def do_GET(self): 
        # 1. Отправляем код ответа (200 = OK)
        self.send_response(200)
        # 2. Отправляем заголовки (headers)
        self.send_header("Content-type", "text/html; charset=utf-8")
        self.end_headers()
        # 3. Отправляем тело ответа
        self.wfile.write("Hello METANIT.COM".encode("utf-8"))

# Настройки запуска
hostName = "localhost"
serverPort = 8000

# Инициализация сервера
webServer = HTTPServer((hostName, serverPort), MyHandler)
print(f"Сервер запущен: http://{hostName}:{serverPort}")

try:
    # Бесконечный цикл прослушивания порта
    webServer.serve_forever()
except KeyboardInterrupt:
    # остановка по Ctrl+C
    print("Работа сервера прервана")

webServer.server_close()
print("Сервер остановлен...")

Рассмотрим код. Предже всего мы определяем обработчик запросов - подкласс BaseHTTPRequestHandler, который пусть называется MyHandler:

class MyHandler(BaseHTTPRequestHandler):
    # обработка get-запросов
    def do_GET(self): 
        # 1. Отправляем код ответа (200 = OK)
        self.send_response(200)
        # 2. Отправляем заголовки (headers)
        self.send_header("Content-type", "text/html; charset=utf-8")
        self.end_headers()
        # 3. Отправляем тело ответа
        self.wfile.write("Hello METANIT.COM".encode("utf-8"))

Пусть наш обработчик обрабатывает только базовые - GET-запросы. Для обработки таких запросов в классе надо определить метод do_GET(). Причем это самая минимально необходимая схема обработки запросов, еоторая состоит из трех частей. Сначала с помощью метода send_response() отправляет статусный код ответа:

self.send_response(200)

Далее нам надо указать клиенту, какой тип ответа отправляется:

self.send_header("Content-type", "text/html; charset=utf-8")
self.end_headers()

Стоит отметить, что вызов self.end_headers() необходим, чтобы заголовки, отправленные через self.send_header(), реально отправились, а не остались в буфере.

В данном случае будем рассматривать ответ как код html в кодировке "utf-8".

В конце отправляем собственно тело ответа с помощью метода self.wfile.write():

self.wfile.write("Hello METANIT.COM".encode("utf-8"))

self.wfile - это "файл записи": все, что записывается сюда, отправится обратно клиенту (браузеру). Однако сеть работает с байтами, и в метод self.wfile.write() передается набор байтов. Поэтому для отправки строка преобразуется в набор байтов с помощью вызова encode("utf-8")

Далее устанавливаем настройки запуска - будем запускать локально на порту 8000:

hostName = "localhost"
serverPort = 8000

Далее инициализируем объект сервера, передавая в него адрес запуска и класс обработчика запросов:

webServer = HTTPServer((hostName, serverPort), MyHandler)

Далее в конструкции try..except запускаем сервер и начинаем прослушивать входящие запросы:

try:
    # Бесконечный цикл прослушивания порта
    webServer.serve_forever()
except KeyboardInterrupt:
    # остановка по Ctrl+C

    print("Работа сервера прервана")
webServer.server_close()

Поскольку HTTPServer - подкласс socketserver.TCPServer, то соответственно наследует его методы для работы с запросами. Например, для запуска и прослушивания входящих запросов применяется унаследованный метод serve_forever(). А для завершения сервера и освобождения ресурсов используется унаследованный метод server_close()

Стоит учитывать, что метод serve_forever() фактически запускает бесконечный цикл для прослушивания входящих запрос. И чтобы выйти из этого цикла в консоли можно применить стандартное сочетание клавиш Ctrl+C. Поэтому в конструкции try..except с помощью отслеживания исключения KeyboardInterrupt, мы можем отловить нажатие этих клавиш и выполнить некоторые действия - в данном случае просто выводим уведомление на консоль.

И после завершения прослушивания запросов завершаем работу сервера, выполняя метод server_close()

Запустим скрипт на выполнение (в моем случае это файл app.py):

eugene@Eugene:~/python/httpserver$ python3 app.py
Сервер запущен: http://localhost:8000

Перейдем по адресу "http://localhost:8000" в браузере:

HTTP-сервер на Python с помощью класса HTTPServer

При обращении по адресу наш http-сервер получит запрос и отправит в ответ строку. Тем временем консоль все это запротоколирует:

eugene@Eugene:~/python/httpserver$ python3 app.py
Сервер запущен: http://localhost:8000
127.0.0.1 - - [08/Dec/2025 16:05:49] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [08/Dec/2025 16:05:49] "GET /favicon.ico HTTP/1.1" 200 -

Для выхода из сервера нажмем Ctrl+C (Ctrl+Alt+C):

eugene@Eugene:~/python/httpserver$ python3 app.py
Сервер запущен: http://localhost:8000
127.0.0.1 - - [08/Dec/2025 16:05:49] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [08/Dec/2025 16:05:49] "GET /favicon.ico HTTP/1.1" 200 -
^CРабота сервера прервана
Сервер остановлен...
eugene@Eugene:~/python/httpserver$
Помощь сайту
Юмани:
410011174743222
Номер карты:
4048415020898850