Всем привет! На повестке дня рубрика python. Сегодня мы реализуем простейший сервер на языке программирования python. Поехали!
Я буду пользоваться python версии 3.5.2 Работу осуществлять в операционной системе linux, так как ее использует большинство серверов.
Создадим файл server.py. И начнем подключение модулей. Для создания сервера нам понадобится модуль http.server, точнее его объекты BaseHTTPRequestHandler и HTTPServer.
Изъять их можно с помощью такой строчки кода:
from http.server import BaseHTTPRequestHandler, HTTPServer
Далее используя объекты и их методы пишем сервер.
from http.server import BaseHTTPRequestHandler, HTTPServer
class myHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
message = "Server working!"
self.wfile.write(bytes(message, "utf8"))
return
server = HTTPServer(('127.0.0.1', 8081), myHandler)
server.serve_forever()
Что мы здесь видим? Для создания сервера используется объект HTTPServer(). В него мы передаем аргументы. Ip адрес и порт('127.0.0.1', 8081) обращаясь к которым мы можем видеть что отдает сервер. Здесь для примера, я использую локальный адреc 127.0.0.1(localhost). Если вы хотите запустить сервер на определенном домене просто введите его ip адрес. Далее, вторым аргументом у нас идет название класса(myHandler) через который мы будем реализовывать обработчик приема и отправки запросов.
С помощью строчки:
server.serve_forever()
сервер запускается.
В самом классе myHandler() в качестве его родителя мы указываем класс BaseHTTPRequestHandler(). Это нам нужно для получения специальных методов для обработки запросов.
И первый метод который мы рассмотрим это do_GET(). Данный метод обрабатывает все GET запросы. Здесь мы обращаемся к специальным методам.
send_response(200) - код возврата, 200 это успешное подключение
send_header('Content-type','text/html') - заголовок ответа, указываем тип контента html
end_headers() - завершаем передачу заголовков и отправляем их для установления соединения
self.wfile.write(bytes(message, "utf8")) - с помощью данной строчки мы отдаем ответ от сервера, а именно в качестве ответа будет значение переменной message. Функция bytes() кодирует строку в определенную кодировку, в нашем случае это utf8.
В конце я поставил return, это не обязательно но желательно.
И так, теперь запустим сервер, просто запустив файл server.py
В linux это можно сделать так:
python3 server.py
В итоге мы запускаем сервер и теперь в браузере перейдя по адресу http://127.0.0.1:8081 или http://localhost:8081 можем видеть ответ Server working!(это значение нашей переменной message). Чтобы остановить сервер просто нажмите ctrl + c в консоли. Наш сервер в конечном итоге готов. Вот так просто!
Закрепляем информацию! Сейчас мы напишем небольшой шаблонизатор который на выходе будет отдавать html странички.
Создадим папку pages и в нее поместим четыре html страницы: index.html, news.html, support.html, 404.html.
Содержимое файлов:
index.html - главная страница
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<title>
Главная
</title>
</head>
<body>
<h1>
Добро пожаловать на наш сервер
</h1>
<a href="/">Главная страница</a>
<a href="/news">Страница новостей</a>
<a href="/support">Обратная связь</a>
</body>
</html>
news.html - страница новостей
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<title>
Новости
</title>
</head>
<body>
<h1>
Страница новостей
</h1>
<a href="/">Главная страница</a>
<a href="/news">Страница новостей</a>
<a href="/support">Обратная связь</a>
</body>
</html>
support.html -страница обратной связи
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<title>
Обратная связь
</title>
</head>
<body>
<h1>
Обратная связь
</h1>
<a href="/">Главная страница</a>
<a href="/news">Страница новостей</a>
<a href="/support">Обратная связь</a>
<br>
<br>
<form action="/email" method="post">
<input type="text" name="email" placeholder="Введите email" type="email" />
<button type="submit">Подписаться</button>
</form>
</body>
</html>
404.html - страница не найдена
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8">
<title>
Страница не найдена
</title>
</head>
<body>
<h1>
Страница не найдена!
</h1>
</body>
</html>
Затем пишем шаблонизатор для переходов по страницам. В итоге получается:
from http.server import BaseHTTPRequestHandler, HTTPServer
class myHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
path = self.path
if path == "/":
path = "/index"
try:
file = open("pages"+path + ".html", 'r')
except FileNotFoundError:
file = open("pages/404.html", 'r')
message = file.read()
file.close()
self.wfile.write(bytes(message, "utf8"))
return
server = HTTPServer(('127.0.0.1', 8081), myHandler)
server.serve_forever()
Здесь у нас уже в переменную message записывается содержимое определенного html файла и в результате по запросу выводится страница.
С помощью self.path мы получаем url адрес введенный пользователем. К примеру http://localhost.8081/news, мы получим значение /news и т.п.
Если шаблон шаблон не найден у нас срабатывает исключение FileNotFoundError и в результате выводится страница 404.html
Посмотрим как это работает.
Здесь как видите у нас получилось сделать рабочий сайт с переходами по страницам. Причем если мы введем несуществующий адрес у нас выведется 404 страница с нашим шаблоном. Вот так, на вашем сервере можно запустить простой статический сайт.
В завершение добавим обработку post запроса нашей формы на странице support.html. Так вы узнаете как создавать обработчики форм, получать и обрабатывать из них информацию на сервере.
Обновляю код:
from http.server import BaseHTTPRequestHandler, HTTPServer
import re
class myHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
path = self.path
if path == "/":
path = "/index"
try:
file = open("pages"+path + ".html", 'r')
except FileNotFoundError:
file = open("pages/404.html", 'r')
message = file.read()
file.close()
self.wfile.write(bytes(message, "utf8"))
return
def do_POST(self):
self.send_response(301)
self.send_header('Location','/support')
self.end_headers()
path = self.path
#Обработчик подписки
if path == "/email":
content_len = int(self.headers.get('Content-Length'))
post = self.rfile.read(content_len)
email = re.split(r"email=",str(post))[1]
email = re.sub(r"\'","",email)
print(email)
return
server = HTTPServer(('127.0.0.1', 8081), myHandler)
server.serve_forever()
Для того чтобы работать с POST запросами нужно обратится к методу do_POST(). Заметьте что здесь я передаю уже другие заголовки.
301 - это код перенаправления
send_header('Location','/support') - это заголовок редиректа, то есть при завершении этого запроса я хочу вернуться на страницу support.html
В качестве пути выступает значение нашего атрибута action в форме. С помощью этих двух строчек, мы получаем наши переданные данные:
content_len = int(self.headers.get('Content-Length'))
post = self.rfile.read(content_len)
В переменную post помещается информацию в виде строки байтов в формате (свойство=значение). В нашем случае передан один параметр со свойством email и его значением которое вы ввели в поле при отправке формы. Заметьте что для извлечения значения я воспользовался регулярными выражениями и подключил специальный модуль re. В конечном итоге мы в консоль выводим наше введенное значение.
Вот результат:
Как видите при отправке формы мы остаемся на этой же странице, а наши введенные данные благополучно POST запросом отправляются на сервер и там обрабатываются(выводятся).
На этом данная статья подошла к концу. Надеюсь сегодня вам было интересно и полезно получить подобную информацию. Конечно это мизерная часть по сравнению со всем объемом информации. Но используя данные знания вы уже можете реализовать многое. Хотелось бы побольше поддержки и активности с вашей стороны.
Не забывайте подписываться на мою группу ВК или блог. Так вы сможете получать информацию о выходе новых статей в ВК или на почту.
У меня также есть канал на youtube.На этом у меня все. Желаю вам успехов и удачи! Пока.