Одна из содержательных частей цикла запрос-ответ — обработчик запроса. В этом уроке мы разберем, как находить и вызывать обработчика.
Обработчик
Общий принцип работы любого веб-фреймворка отражает архитектуру HTTP. На каждый адрес задается обработчик (handler) — функция, которая выполняет необходимые действия и возвращает ответ.
Обработчики регистрируются с помощью декоратора @route()
. Декоратор принимает путь или маршрут, для которого вызовется обработчик:
@app.route('/')
def index():
# …
@app.route('/data/users/')
def users():
# …
Каждый путь состоит из сегментов — строк, которые разделены слешами ("/"). Функции index
и users
в примере — обработчики, а каждое применение декоратора route
— добавление нового правила маршрутизации.
Во фреймворках принято определять маршрут как комбинацию метода HTTP и адреса. И это соответствует идеям REST. Flask предлагает два способа указания метода:
- Как аргумент декоратора
route()
— все указанные методы будут обрабатываться одной функцией, а выбор метода будет в условиях:
from flask import request
@app.route("/", methods=["GET", "POST"])
def hello():
# Получить доступ к содержимому запроса можно через специальный объект request
if request.method == "POST":
return "Hello, POST!"
return "Hello, GET!"
- Как отдельные обработчики под каждый метод с помощью соответствующих декораторов:
get()
,post()
и других:
@app.get("/")
def hello_get():
return "Hello, GET!"
@app.post("/")
def hello_post():
return "Hello, POST!"
Теперь с помощью утилиты curl
мы можем выполнить запросы к нашему приложению и проверить, какие сообщения выводятся при GET и POST-запросах:
curl -X GET localhost:8000
# Hello, GET!
curl -X POST localhost:8000
# Hello, POST!
Диспетчеризация
Процесс поиска нужного обработчика называется диспетчеризацией. Она выполняется в два этапа: до входа во фреймворк и после входа в приложение. Разберем шаги каждого этапа.
До входа в фреймворк:
- Клиент выполняет запрос к веб-серверу, который расположен на сервере. Клиент — это не обязательно браузер, в примере клиент — это программа
curl
- Веб-сервер перенаправляет запрос приложению и устанавливает правильные параметры запроса
После входа в приложение — происходит диспетчеризация:
- Фреймворк анализирует параметры запроса и пытается сопоставить маршруты, которые добавлены в объект
app
с тем, что пришло. Он сравнивает комбинацию адреса и метода. Если метод не указан в правиле, то по умолчанию предполагается GET. Этот процесс называется роутингом или маршрутизацией. А место, где внутри хранятся все добавленные маршруты, называют роутером - Если в процессе роутинга нашелся соответствующий маршрут, то вызывается его обработчик
- Ответ, который сформировал обработчик, отправляется обратно клиенту
Рассмотрим конкретный пример:
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def index():
return "Hello, World!"
@app.route("/users/", methods=["GET", "POST"])
def users():
if request.method == "POST":
return "Hello from POST /users/"
return "Hello from GET /users/"
После запуска этого кода формируется роутер, который содержит в себе три маршрута. Посмотреть карту маршрутов можно командой flask routes
:
export FLASK_APP=example:app
python -m flask routes
Endpoint Methods Rule
-------- --------- -----------------------
index GET /
users GET, POST /users/
# Flask по умолчанию также создает маршрут для static файлов, мы его не рассматриваем в этом уроке
Теперь предположим, что клиент выполнил такой запрос:
curl -X POST localhost:8000/users
# Hello from POST /users/
После этого последуют следующие действия:
- Веб-сервер вызвал наше приложение
app
- Фреймворк сопоставил маршрут
POST /users
и нашел, что за этот запрос отвечает обработчикusers()
- Фреймворк вызвал обработчик, который вернул клиенту ответ:
'Hello from POST /users'
Фреймворк может не обнаружить соответствия. Например, если клиент запросит страницу /comments. Тогда фреймворк по умолчанию возьмет управление на себя и автоматически отдаст браузеру ответ 404 — страница не найдена:
curl localhost:8000/comments
# <!doctype html>
# <html lang=en>
# <title>404 Not Found</title>
# <h1>Not Found</h1>
# <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
Всегда внимательно смотрите, какие делаются запросы и есть ли подходящие под них ответы. Так вам не придется задаваться вопросом, почему браузер ничего не показывает. Проще всего увидеть ответ от сервера через консоль разработчика вашего браузера:
Она есть в каждом браузере. Попробуйте открыть ее и понаблюдать за процессом загрузки.
Самостоятельная работа
Добавьте обработчики в файл example.py, который мы создали в самостоятельной работе предыдущего урока:
@app.get("/users")
def users_get():
return "GET /users"
@app.post("/users")
def users_post():
return "POST /users"
Откройте в браузере эту страницу. Убедитесь что на экран вывелся текст, переданный в GET-обработчике. Выполните POST-запрос с помощью curl. Убедитесь, что вывелся текст, переданный в POST-обработчике.
Эталонное приложение
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.