Веб-серверы есть везде.
Черт возьми, вы взаимодействуете с одним прямо сейчас!
Независимо от того, какой вы разработчик программного обеспечения, в какой-то момент вашей карьеры вам придется взаимодействовать с веб-серверами. Может быть, вы создаете сервер API для бэкэнда. Или, может быть, вы просто настраиваете веб-сервер для своего сайта.
В этой статье мы расскажем, как создать самый простой http веб-сервер на Python.
Но поскольку мы хотим убедиться, что вы понимаете, что мы создаем, мы сначала дадим обзор о том, что такое веб-серверы и как они работают.
Если вы уже знаете, как работают веб-серверы, вы можете сразу перейти к этому разделу.
- Что такое HTTP-сервер?
- Адрес сокета TCP
- Создайте простой файл HTTP
- Создать HTTP веб-сервер
Что такое HTTP-сервер?
Веб-сервер HTTP – это не что иное, как процесс, который выполняется на вашем компьютере и выполняет ровно две вещи:
1- Прослушивает входящие HTTP-запросы на определенный адрес сокета TCP (IP-адрес и номер порта, о которых мы расскажем позже)
2- Обрабатывает этот запрос и отправляет ответ обратно пользователю.
Но что на самом деле происходит под капотом?
На самом деле много чего происходит, и мы могли бы посвятить целую статью, чтобы объяснить магию, как это произошло.
Но для простоты мы отвлечемся от некоторых деталей и расскажем об этом на очень высоком уровне.
На высоком уровне, когда вы набираете www.yandex.ru в своем браузере, ваш браузер создаст сетевое сообщение, называемое HTTP-запросом.
Этот запрос будет распространяться на компьютер yandex, на котором работает веб-сервер. Этот веб-сервер перехватит ваш запрос и обработает его, отвечая HTML-кодом домашней страницы yandex.
Наконец, ваш браузер отображает этот HTML на экране, и это то, что вы видите на своем экране.
Каждое взаимодействие с домашней страницей yandex после этого (например, когда вы нажимаете на ссылку) инициирует новый запрос и ответ точно так же, как первый.
Повторим еще раз: на машине, которая получает запрос http, работает программный процесс, называемый веб-сервером. Этот веб-сервер отвечает за перехват этих запросов и их обработку соответствующим образом.
Хорошо, теперь, когда вы знаете, что такое веб-сервер и какова его функция, вам может быть интересно, как запрос в первую очередь достигает машины yandex?
Хороший вопрос!
Позвольте нам объяснить, как, но опять же … на высоком уровне.
Адрес сокета TCP
Любое http-сообщение (будь то запрос или ответ) должно знать, как добраться до места назначения.
Чтобы достичь места назначения, каждое http-сообщение содержит адрес, называемый адресом TCP назначения.
И каждый TCP-адрес состоит из IP-адреса и номера порта.
Мы знаем, что все эти аббревиатуры (TCP, IP и т. д.) могут быть ошеломляющими, если ваши сетевые знания не сильны.
Так где же этот адрес, когда все, что вы сделали, и набрали www.yandex.ru в вашем браузере?
Ну, это доменное имя преобразуется в IP-адрес через большую распределенную базу данных, называемую DNS.
Хотите проверить, что это за IP-адрес?
Легко! Зайдите в свой терминал и сделайте следующее:
$ host yandex.ru Yandex.ru has address 77.88.55.66 Yandex.ru has address 5.255.255.70 Yandex.ru has address 77.88.55.70 Yandex.ru has address 5.255.255.60 Yandex.ru has IPv6 address 2a02:6b8:a::a Yandex.ru mail is handled by 10 mx.Yandex.ru.
Как видите, как DNS переведет yandex.ru на любой из указанных выше адресов.
Один только IP-адрес позволит HTTP-сообщению поступить на нужный компьютер, но вам все равно нужен номер порта, чтобы HTTP-запрос поступил именно на веб-сервер.
Другими словами, веб-сервер – это обычное сетевое приложение, которое прослушивает определенный порт.
И HTTP-запрос ДОЛЖЕН быть адресован этому порту.
Так где же номер порта при вводе www.yandex.ru ?
По умолчанию номер порта равен 80 для http и 443 для https, поэтому даже если вы не указали номер порта явно, он все еще там.
И если веб-сервер прослушивает номер порта не по умолчанию (ни 80, ни 443), вы должны явно указать номер порта следующим образом:
www.yandex.ru:445
К настоящему времени у вас должна быть вся необходимая информация для создания http-сервера на Python.
Так что без дальнейших церемоний, давайте начнем.
Создайте простой файл HTML
Вот что мы хотим сделать.
Мы хотим создать простой http-сервер, который обслуживает статическую HTML-страницу.
Давайте создадим нашу HTML-страницу.
<html> <head> <title>Python-это потрясающе!</title> </head> <body> <h1>yandex</h1> <p>Поздравляю! Сервер HTTP работает!</p> </body> </html>
Теперь сохраните этот файл как index.html.
Теперь, для обслуживания веб-страницы, следующим шагом является создание веб-сервера, который будет обслуживать эту HTML-страницу.
Создать HTTP веб-сервер
Чтобы создать веб-сервер в Python 3, вам нужно импортировать два модуля: http.server и socketserver
Обратите внимание, что в Python 2 был модуль с именем SimpleHTTPServer. Этот модуль был объединен с http.server в Python 3
Давайте посмотрим на код для создания http-сервера
import http.server import socketserver PORT = 8080 Handler = http.server.SimpleHTTPRequestHandler with socketserver.TCPServer(("", PORT), Handler) as httpd: print("serving at port", PORT) httpd.serve_forever()
Просто так у нас есть функциональный http-сервер.
Теперь давайте разберем этот код построчно.
Во-первых, как мы упоминали ранее, веб-сервер – это процесс, который прослушивает входящие запросы на определенный TCP-адрес.
И, как вы уже знаете, TCP-адрес идентифицируется по IP-адресу и номеру порта.
Во-вторых, веб-сервер также должен знать, как обрабатывать входящие запросы.
Эти входящие запросы обрабатываются специальными обработчиками. Вы можете думать о веб-сервере как о диспетчере, поступает запрос, http-сервер проверяет запрос и отправляет его назначенному обработчику.
Конечно, эти обработчики могут делать все что угодно.
Но что вы думаете, какой самый основной обработчик?
Ну, это будет обработчик, который просто обслуживает статический файл.
Другими словами, когда мы заходим на yandex.ru, веб-сервер на другом конце отправляет обратно статический HTML-файл.
Это на самом деле то, что мы пытаемся сделать.
И это, и есть то, что является http.server.SimpleHTTPRequestHandler : простой обработчик HTTP-запросов, который обслуживает файлы из текущего каталога и любых его подкаталогов.
Класс socketserver.TCPServer
Теперь поговорим о классе socketserver.TCPServer.
Экземпляр TCPServer описывает сервер, который использует протокол TCP для отправки и получения сообщений (http – это протокол прикладного уровня поверх TCP).
Чтобы создать экземпляр TCP-сервера, нам нужны две вещи:
- TCP-адрес (IP-адрес и номер порта)
- Обработчик
socketserver.TCPServer(("", PORT), Handler)
Как видите, TCP-адрес передается в виде кортежа (IP-адрес, номер порта)
Передача пустой строки в качестве IP-адреса означает, что сервер будет прослушивать любой сетевой интерфейс (все доступные IP-адреса).
А поскольку PORT хранит значение 8080, сервер будет прослушивать входящие запросы на этот порт.
Для обработчика мы передаем простой обработчик, о котором мы говорили ранее.
Handler = http.server.SimpleHTTPRequestHandler
Ну, а как насчет serve_forever?
serve_forever – это метод в экземпляре TCPServer, который запускает сервер и начинает прослушивать и отвечать на входящие запросы.
Круто, давайте сохраним этот файл как server.py в том же каталоге, что и index.html, потому что по умолчанию SimpleHTTPRequestHandler будет искать файл с именем index.html в текущем каталоге.
В этом каталоге запустите веб-сервер:
$ python server.py serving at port 8080
Благодаря этому теперь у вас есть HTTP-сервер, который прослушивает любой интерфейс на порте 8080 и ожидает входящие HTTP-запросы.
Пришло время для забавных вещей!
Откройте браузер и введите localhost:8080 в адресной строке.
Потрясающие! Похоже, все работает нормально.
Но что такое localhost ?
localhost – это имя хоста, которое означает этот компьютер. Он используется для доступа к сетевым службам, работающим на хосте, через петлевой сетевой интерфейс.
А поскольку веб-сервер прослушивает любой интерфейс, он также прослушивает интерфейс обратной связи.
Вы хотите знать, какой IP-адрес соответствует localhost?
Введите следующее:
$ host localhost localhost has address 127.0.0.1 localhost has IPv6 address ::1 Host localhost not found: 3(NXDOMAIN)
Фактически вы можете полностью заменить localhost на 127.0.0.1 в вашем браузере, и вы все равно получите тот же результат.
Одно последнее слово
На самом деле вы можете запустить веб-сервер с python, даже не создавая никаких скриптов.
Просто зайдите в свой терминал и сделайте следующее (но убедитесь, что вы на Python 3)
python -m http.server 8080
По умолчанию этот сервер будет прослушивать все интерфейсы и порт 8080.
Если вы хотите прослушать определенный интерфейс, сделайте следующее:
python -m http.server 8080 --bind 127.0.0.1
Также начиная с Python 3.7, вы можете использовать флаг –directory для обслуживания файлов из каталога, который не обязательно является текущим каталогом.
Таким образом, теперь возникает вопрос: зачем вам когда-либо писать сценарий, когда вы можете просто вызывать сервер из терминала?
Хорошо, помните, что вы используете SimpleHTTPRequestHandler. Если вы хотите создать свои собственные обработчики (что вы, вероятно, захотите), то вы не сможете сделать это из терминала.