MyTetra Share
Делитесь знаниями!
Python: реализуем веб-сервер своими руками
Время создания: 13.07.2018 15:33
Текстовые метки: python http server example
Раздел: Python

Intro


Недавно столкнулся с интересной задачей: нужно было написать программу, которая откликается на указанном порту по протоколу http и генерирует гиперссылку, составленную определенным образом. Приложение должно было быть независимым и поэтому реализовать его просто как веб-страницу не представлялось возможным. Оказалось, что реализовать веб-сервер на Питоне вообще не составляет никакого труда, потому как все необходимое уже присутствует в стандартной библиотеке. Но все по порядку…


Пакет http


Как выяснилось, сам интерпретатор уже имеет в своем составе пакет http, в котором сосредоточены все функции работы с этим протоколом: как серверные, так и клиентские, в виде отдельных модулей. Так как мы пишем сервер, то нас в первую очередь интересует модуль, отвечающий именно за функции обслуживания http-запросов: в Python 3 они объединены в один модуль под названием http.server, в Python 2 эти функции разнесены по трем модулям: BaseHTTPServer, CGIHTTPServer и SimpleHTTPServer.


Обработчик запросов: BaseHTTPRequestHandler


Для реализации простого сервера будет достаточно использовать «класс-заготовку» — BaseHTTPRequestHandler. Этот класс может использоваться как базовый для реализации собственного обработчика запросов, действующего в составе сервера HTTP. После того как клиент установит соединение и HTTP-заголовки его запроса будут проанализированы, выполняется попытка вызвать метод вида do_REQUEST, имя которого определяется исходя из типа запроса: для обработки GET-запроса типа будет вызван метод do_GET(), для обработки POST-запроса – метод do_POST() и так далее. По умолчанию этот класс ничего не делает, и предполагается, что эти методы должны быть переопределены в подклассах. В простейшем случае требуется реализовать лишь метод do_GET():


from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer


class HttpProcessor(BaseHTTPRequestHandler):

def do_GET(self):

self.send_response(200)

self.send_header('content-type','text/html')

self.end_headers()

self.wfile.write("hello !")



Теперь необходимо создать объект класса HTTPServer, передав ему в качестве параметров IP-адрес и порт, на котором будет работать http-сервер, а также наш класс-потомок BaseHTTPRequestHandler, который собственно и будет отвечать за обработку запросов к серверу:


serv = HTTPServer(("localhost",80),HttpProcessor)

serv.serve_forever()



Первой строкой мы создаем экземпляр HTTPServer, указывая ему, по какому адресу и с помощью чего обрабатывать наши http-запросы, затем, вызовом метода serve_forever(), мы указываем интерпретатору перманентно запустить веб-сервер — приложение будет работать до тех пор, пока его работа не будет прервана путем нашего вмешательства. Убедиться в его работоспособности можно, обратившись через браузер по тому адресу, который мы забиндили при написании скрипта: нашему взору предстанет веб-страница с единственной фразой — «hello».


Как это работает


Для ясности, рассмотрим текст метода do_GET():

Перво-наперво, при успешном соединении, необходимо отправить браузеру код ответа -информацию о том, что запрашиваемая страница была обнаружена (код 200: HTTP/ok):


self.send_response(200)



Затем необходимо отправить http-заголовки, для чего используется метод send_header(), а также эскейп-посдедовательность (\r\n\r\n), которая свидетельствует о завершении заголовка ответа:


self.end_headers()



Так как мы установили в заголовках тип содержимого ответа: Content-type: text/html, то весь текст, выведенный нашим методом do_GET(), будет интерпретирован клиентом как HTML-разметка. Также следует обратить внимание на атрибут wfile класса BaseHTTPRequestHandler

. Он представляет собой объект, который реализует поток сервера, транслируемый на клиент. Любой вывод в браузер осуществляется методом wfile.write('something').


В заключение


Предложенный способ реализации может применяться в качестве независимого http-сервера «на скорую руку», легко переносимого (реализован один файлом) и работающего везде, где работает Python. Отмечу лишь, что в данном примере использован интерпретатор Python 2.7. В реализации на Python 3 будут некоторые отличия. Более подробную информацию о пакете http можно получить из официальной документации по языку Python.

Так же в этом разделе:
 
MyTetra Share v.0.53
Яндекс индекс цитирования