Маршрутизация запросов

Маршрутизация запросов #

Документация #

Задачи #

Продолжайте разработку приложения, которую начали на прошлом занятии. В рамках текущего занятия необходимо добавить отображение страниц с детальной информацией о конкретном треугольнике. Сначала задачу необходимо реализовать с помощью метода маршрутизации, предоставляемом библиотекой http4, а затем реализовать свою собственную функцию по маршрутизации.

На каждой странице сайта должна показываться навигационная панель, в которой есть ссылка на страницу со списком треугольников.

Ниже представлены шаги по решению данной задачи.

Отображение информации о треугольнике #

Реализуйте отображение информации о треугольнике на отдельной странице. На данной странице необходимо выводить всю информацию о конкретном треугольнике. Маршрут для отображения элемента списка /triangle/{number}, где number — это порядковый номер в списке треугольников. На странице также необходимо отображать ссылку для перехода к списку треугольников.

  1. Создайте компонент для формирования HTML-документа, описывающего данные для конкретного треугольника, ru.yarsu.web.view.TriangleView. В качестве входных данных компонент должен принимать ссылку на объект треугольника, Triangle. В качестве выхода он должен формировать HTML-документ с описанием треугольника.
  2. Создайте класс HTTP-обработчика для отображения детальной информации о треугольнике.
    1. Создайте класс ru.yarsu.web.handlers.ShowTriangleHandler.
    2. Конструктор класса должен принимать ссылку на объект класса Triangles.
    3. Реализуйте функцию invoke, логику по обработке HTTP-запроса. Внутри данной функции:
      1. Получите порядковый номер треугольника из переменной пути number. Для извлечения значения данной переменной из пути используйте функцию Request.path.
      2. Преобразуйте полученную строку к числу с использованием функции toIntOrNull(). На настоящий момент будем подразумевать, что передаваемые данные корректны.
      3. Получите ссылку на указанный треугольник из списка треугольников, Triangles. С помощью функции fetchTriangleByNumber(number: Int).
      4. Сформируйте HTML-документ с помощью компонента TriangleView.
      5. Сформируйте HTTP-ответ, содержащий статус OK и HTML-документ в теле ответа.
  3. Свяжите созданный HTTP-обработчик с маршрутом /triangle/{number} внутри функции по формированию маршрутизатора, router. Передайте функции по созданию обработчику ссылку на объект Triangles.

Обработка ошибочного параметра #

Доработайте обработчик маршрута /triangle/{number} таким образом, чтобы приложение вело себя корректно в следующих ситуациях:

  1. Переданный аргумент не содержит целого числа.
  2. Передан некорректный номер треугольника в списке.

В данных случаях приложение должно сообщать пользователю о неправильных параметрах.

Создание собственного маршрутизатора #

Подсистема для связывания путей с обработчиками маршрутов в http4k очень гибкая:

  • Позволяет связывать обычные обработчики маршрута с путями.
  • Позволяет связывать маршрутизируемые обработчики с путями.
  • Позволяет объединять маршрутизируемые обработчики вместе.

С её помощью можно реализовать практически любой подход к описанию логики маршрутизации в системе. Настоятельно рекомендуется использовать именно родную подсистему для выполнения маршрутизации внутри приложения.

В рамках данной части занятия предлагается задача по созданию собственной, гораздо более простой, версии функции-маршрутизатора. Будем работать в следующих ограничениях:

  • Разрабатываем функцию специально для данного приложения. Не надо пытаться решить общую задачу, как это сделано в наборе функций от библиотеки http4k.
  • Обработчики HTTP-запросов не должны знать об изменениях в маршрутизаторе.

Как работает функция Request.path #

Ввиду последнего ограничения необходимо обеспечить работу обработчика HTTP-запроса ru.yarsu.ShowTriangleHandler. Данный обработчик извлекает данные с помощью метода Request.path. Рассмотрим его реализацию:

fun Request.path(name: String): String? = when (this) {
    is RequestWithRoute -> xUriTemplate.extract(uri.path)[name]
    else -> throw IllegalStateException("Request was not routed, so no uri-template present")
}

Из реализации видно, что функция работает не с интерфейсом Request, а с интерфейсом RequestWithRoute. Единственный класс, который реализует данный интерфейс внутри библиотеки http4k — это

RoutedRequest(private val delegate: Request, override val xUriTemplate: UriTemplate)
  : Request by delegate, RequestWithRoute
Таким образом внутрь HTTP-обработчика надо передавать объекты класса RoutedRequest, соединяющие в себе оригинальный объект запроса и шаблон шаблон стандартной подсистемы маршрутизации.

Работа с путём запроса #

Внутри объектов Request содержится поле uri, которое содержит внутри себя объект Uri, описывающий URI-путь внутри запроса. Путь запроса содержится внутри поля path данного объекта.

Путь — это строка, класс String, которую можно обрабатывать с помощью любых функций для строк, например:

  • split для разделения строк на части,
  • startsWith для проверки префикса строки.

Реализация функции-маршрутизатора #

  1. Создайте новый HTTP-обработчик, ru.yarsu.web.handlers.AppRouter.
  2. Конструктор класса должен принимать ссылки на другие HTTP-обработчики.
  3. Внутри функции по обработке HTTP-запроса выполните следующие действия:
    1. Сравните весь путь со строкой "/". Если он совпал, то передайте обработку запроса объекту класса "ru.yarsu.web.handlers.RedirectToTriangleListHandler".
    2. Сравните весь путь со строкой "/ping". Если он совпал, то передайте обработку запроса объекту класса ru.yarsu.web.handlers.PongHandler.
    3. Сравните весь путь со строкой "/triangles". Если он совпал, то передайте обработку запроса объекту класса "ru.yarsu.web.handlers.ListTrianglesHandler".
    4. Проверьте, что путь начинается со строки "/triangles/". Если условие выполнилось, то передайте обработку запроса объекту ru.yarsu.ShowTriangleHandler. Перед передачей запроса в обработчик оберните объект запроса оберните класс RoutedRequest. В качестве шаблона пути используйте /triangles/{number}
    5. Если ни одна из проверок не была выполнена, то верните ответ с кодом 404, NOT_FOUND.
  4. Используйте объект класса ru.yarsu.web.handlers.AppRouter в качестве основного обработчика HTTP-запросов внутри приложения. Удостоверьтесь, что все HTTP-запросы корректно обрабатываются приложением, пользователю доступны все ссылки.

© A. M. Васильев, 2023, CC BY-SA 4.0, andrey@crafted.su