Простой http сервер.¶
Любой online-сервис начинается с того, что необходимо приложение, которое способно принимать и обрабатывать http-запросы.
В python есть встроенный модуль, который полвзоляет создавать простой http-сервер.
from http.server import BaseHTTPRequestHandler from http.server import HTTPServer def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler): server_address = ('', 8000) httpd = server_class(server_address, handler_class) try: httpd.serve_forever() except KeyboardInterrupt: httpd.server_close()
Если запустить функцию run() , то будет запущен http-сервер, и если в браузере Вы введете 127.0.0.1:8000 , то Вам вернутся ответ, но ответ будет содержать ошибку, потому что сервер не знает как обрабатывать запросы.
Для того что бы исправить эту ошибку трубется в обработчике( BaseHTTPRequestHandler ) реализовать метод по обработке GET-запросов:
class HttpGetHandler(BaseHTTPRequestHandler): """Обработчик с реализованным методом do_GET.""" def do_GET(self): self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(''.encode()) self.wfile.write(''.encode()) self.wfile.write('Был получен GET-запрос.'.encode())
Теперь, если запустить сервер с новым обработчиком run(handler_class=HttpGetHandler) , то при переходе по адресу 127.0.0.1:8000 можно будет увидеть ответ на запрос.
Обратите внимание, что при формировании ответа обработчика был использован метод encode() у строк. Сделано этого потому что в теле ответа могут быть использованы только байтовые строки.
Задания¶
- Ознакомьтесь с описанием протокола HTTP.
- Дополните обработчик запросов таким образом, что бы он мог обрабатывать запросы по методам POST, PUT и HEAD. Для проверки реализации используйте библиотку requests.
© Copyright Revision d00c0df4 .
Versions latest Downloads html On Read the Docs Project Home Builds Free document hosting provided by Read the Docs.
Python: реализуем веб-сервер своими руками
Недавно столкнулся с интересной задачей: нужно было написать программу, которая откликается на указанном порту по протоколу 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):
Затем необходимо отправить http-заголовки, для чего используется метод send_header(), а также эскейп-посдедовательность (\r\n\r\n), которая свидетельствует о завершении заголовка ответа:
Так как мы установили в заголовках тип содержимого ответа: Content-type: text/html, то весь текст, выведенный нашим методом do_GET(), будет интерпретирован клиентом как HTML-разметка. Также следует обратить внимание на атрибут wfile класса BaseHTTPRequestHandler
. Он представляет собой объект, который реализует поток сервера, транслируемый на клиент. Любой вывод в браузер осуществляется методом wfile.write(‘something’).
В заключение
Предложенный способ реализации может применяться в качестве независимого http-сервера «на скорую руку», легко переносимого (реализован один файлом) и работающего везде, где работает Python. Отмечу лишь, что в данном примере использован интерпретатор Python 2.7. В реализации на Python 3 будут некоторые отличия. Более подробную информацию о пакете http можно получить из официальной документации по языку Python.
BaseHTTPServer
That is, make a subclass of the server, that accepts some additional parameters. Have the server record those parameters.
Then, in the handler, use s.server to get to the server, and access the parameters through it.
See Also
- DocXmlRpcServer — self-documenting XML-RPC servers
- CgiScripts — using invoked CGI scripts, rather than running micro-web servers
Discussion
I’d ultimately like to see a BaseHttpServer here that can both handle XML-RPC requests (with that request handler,) and normal web requests (with a custom handler.)
Yes- I know and love TwistedPython. But I want to make something that works in a single install. — LionKimbro 2004-05-31 01:13:16
I’d also like to add code here showing how to service a POST request.
There exist tools like CherryPy which will create a single-file Python HTTP server (based on BaseHTTPServer). This is a fair amount easier to work with than the raw BaseHTTPServer. For most cases, using a more complete framework will be preferable (see WebProgramming). — IanBicking
I like the BaseHttpServer because it is in the default Python distributions. I encourage all work towards putting a standard web framework into the default Python distribution. I’m not picky, just as long as something is chosen. — LionKimbro 2005-01-25 04:53:53
What’s the matter with server_close()? I can call the method, but it is undocumented (see http://docs.python.org/lib/node634.html). Could someone knowledgable either remove the calls, or add a comment why they’re necessary? Thanks. — Anonymous Coward, 23 Oct 2007
BaseHttpServer (last edited 2012-04-15 19:54:19 by PaulBoddie )