Зарегистрируйтесь, чтобы продолжить обучение

Роутинг в Fiber веб-приложении Веб-разработка на Go

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

В этом уроке мы разберем понятие маршрутизации. В веб-разработке — это важная составляющая, потому что она определяет, как веб-приложение обрабатывает различные HTTP-запросы пользователей.

Что такое роутинг

В Go-приложениях вся бизнес-логика описывается в обработчиках. Каждый обработчик — это логика поведения веб-приложения на определенный HTTP-запрос от клиента. Но веб-приложению нужно определить, какой обработчик используется для определенного запроса.

Когда веб-приложение получает запрос от клиента, оно сопоставляет HTTP-запрос с существующими обработчиками. Процесс определения обработчика по запросу называется маршрутизацией или роутингом.

Чаще всего роутинг осуществляется двумя способами:

  • По пути HTTP-запроса
  • По HTTP-методу запроса

Разберем каждый подход подробнее.

Роутинг по пути HTTP-запроса

Роутинг по пути HTTP-запроса используется во всех веб-приложениях. Путь — это часть URL, которая идет после домена. Например, в URL https://example.com/about путь — это /about.

Правила сопоставления пути HTTP-запроса с обработчиком описываются в коде при инициализации веб-приложения:

package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/sirupsen/logrus"
)

func main() {
    webApp := fiber.New()

    webApp.Get("/path1", path1Handler)
    webApp.Get("/path2", path2Handler)
    ...

    logrus.Fatal(webApp.Listen(":80"))
}

Когда приходит новый запрос от клиента, веб-приложение ищет соответствующий обработчик по пути HTTP-запроса. В примере выше при запросе по пути /path1 будет вызван обработчик path1Handler, а при запросе по пути /path2 будет вызван обработчик path2Handler.

Мы видим, чтобы в Fiber настроить роутинг на GET HTTP-запрос, достаточно вызвать метод webApp.Get() и передать путь HTTP-запроса с нужным обработчиком.

Рассмотрим маршрутизацию по пути HTTP-запроса на конкретном примере. Нам нужно реализовать веб-приложение с обучающими курсами. Оно должно уметь обрабатывать два типа запросов:

  • Запрос по пути /about должен возвращать текст «The best school for Software Engineers»
  • Запрос по пути /courses должен возвращать список курсов. Мы будем возвращать список курсов в виде строки «Java, Go, Python»
package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/sirupsen/logrus"
)

func main() {
    webApp := fiber.New()

    // Настраиваем обработчик по пути "/about"
    webApp.Get("/about", func(c *fiber.Ctx) error {
        return c.SendString("The best school for Software Engineers")
    })

    // Настраиваем обработчик по пути "/courses"
    webApp.Get("/courses", func(c *fiber.Ctx) error {
        return c.SendString("Java, Go, Python")
    })

    logrus.Fatal(webApp.Listen(":80"))
}

Запускаем веб-приложение и переходим в браузере на страницу со списком курсов: http://localhost/courses. Видим, что в ответ пришло сообщение "Java, Go, Python".

Если мы перейдем на страницу с информацией о компании http://localhost/about — в ответ приходит строка "The best school for Software Engineers".

Веб-приложение понимает, какой обработчик необходимо вызвать по пути HTTP-запросов. Поэтому мы получаем в ответе сообщение, которое соответствует HTTP-запросу. Но что будет, если мы отправим HTTP-запрос по несуществующему пути?

Если отправить запрос по несуществующему пути, например, /about2, то ответ будет таким: «Cannot GET /about2» с HTTP статусом 404 Not Found. Так происходит, потому что мы не настроили обработчик для пути /about2, и веб-приложение не знает, какой обработчик ему вызвать. В таком случае возвращается стандартный ответ с HTTP-статусом 404 Not Found.

Мы разобрали, как настроить роутинг по HTTP-запросам. В нашем примере веб-приложение только возвращало запрашиваемые данные. В иных случаях нам часто требуется не только возвращать данные, но и изменять их. Для этого используется роутинг по методам HTTP-запросов.

Роутинг по HTTP-методу запроса

HTTP-метод — это метод, который указывает, какое действие нужно выполнить по HTTP-пути запроса. Мы рассмотрим два наиболее популярных HTTP-метода:

  • GET — получение данных
  • POST — создание или изменение данных

В Fiber роутинг по HTTP-методу запроса настраивается с помощью специальных функций:

  • webApp.Get() — для роутинга GET-запросов
  • webApp.Post() — для роутинга POST-запросов

Рассмотрим роутинг по HTTP-методам на конкретном примере. Предположим, что мы разрабатываем онлайн-счетчик, который умеет обрабатывать следующие HTTP-запросы:

  • POST /counter, который увеличивает счетчик на единицу
  • GET /counter, который возвращает текущее значение счетчика и не изменяет его состояние

В этих HTTP-запросах совпадает путь, но различаются методы. И именно по ним веб-приложение понимает, какой обработчик нужно вызывать.

Так это выглядит на Go с использованием фреймворка Fiber:

package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/sirupsen/logrus"
    "strconv"
)

var counter int64 = 0

func main() {
    webApp := fiber.New()

    webApp.Get("/counter", func(c *fiber.Ctx) error {
        return c.SendString(strconv.FormatInt(counter, 10))
    })

    webApp.Post("/counter", func(c *fiber.Ctx) error {
        counter++

        return c.SendStatus(fiber.StatusOK)
    })

    logrus.Fatal(webApp.Listen(":80"))
}

Запускаем веб-приложение, открываем браузер и переходим на страницу http://localhost/counter. В ответ получаем строку «0». Нам вернулся корректный ответ, потому что мы еще не увеличивали счетчик.

Счетчик увеличивается с помощью POST-запроса. Есть разные способы осуществить такой запрос, но проще всего использовать утилиту curl. Для этого открываем терминал и выполняем следующую команду:

curl -X POST -v 'http://localhost/counter'

В ответ получаем статус «HTTP/1.1 200 OK» — успешное выполнение запроса. Переходим на страницу http://localhost/counter в браузере и видим, что счетчик увеличился на единицу.

Мы можем бесконечно увеличивать счетчик, и в любой момент при переходе на страницу http://localhost/counter мы получим текущее значение счетчика.

Так мы реализовали веб-приложение, которое умеет обрабатывать HTTP-запросы с разными методами, но одинаковыми путями.

Во всех примерах мы описывали статичные пути, когда запрос точно совпадает с описанным путем обработчика. В некоторых приложениях такого подхода недостаточно из-за дополнительных требований. Разберем, как их можно реализовать.

Что такое динамический роутинг и как его реализовать

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

Чтобы работать с различными счетчиками, добавим возможность указывать название события в пути запроса. Например, для события click будет путь запроса /counter/click, а для события view — путь запроса /counter/view. Событий может быть много, поэтому нам нужно описать их. Для этого используем динамический роутинг.

Динамический роутинг позволяет указывать часть пути HTTP-запроса, которая будет изменяться в зависимости от запроса. Например, в нашем случае мы можем указать, что часть пути запроса /counter будет всегда одинаковой. При этом вторая часть пути запроса будет меняться в зависимости от события /counter/:event:

package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/sirupsen/logrus"
    "strconv"
)

var counters = make(map[string]int64)

const requestParamKeyEvent = "event"

func main() {
    webApp := fiber.New()

    webApp.Get("/counter/:event", func(c *fiber.Ctx) error {
        event := c.Params(requestParamKeyEvent, "")
        if event == "" {
            return c.SendStatus(fiber.StatusUnprocessableEntity)
        }

        eventCounter, ok := counters[event]
        if !ok {
            return c.SendStatus(fiber.StatusNotFound)
        }

        return c.SendString(strconv.FormatInt(eventCounter, 10))
    })

    webApp.Post("/counter/:event", func(c *fiber.Ctx) error {
        event := c.Params(requestParamKeyEvent, "")
        if event == "" {
            return c.SendStatus(fiber.StatusUnprocessableEntity)
        }

        counters[event] += 1

        return c.SendStatus(fiber.StatusOK)
    })

    logrus.Fatal(webApp.Listen(":80"))
}

Запустим приложение и проверим его работу. Для начала увеличим счетчик нескольких событий, а затем проверим, что у них корректное состояние:

  1. Отправим POST-запрос на http://localhost/counter/clicks три раза
  2. Откроем в браузере страницу http://localhost/counter/clicks и проверим, что счетчик события clicks равен трем
  3. Отправим POST-запрос на http://localhost/counter/views два раза
  4. Откроем в браузере страницу http://localhost/counter/views и проверим, что счетчик события views равен двум

Мы увеличили счетчики двух событий: clicks и views. После этого мы получили и проверили значения обоих счетчиков. Благодаря динамическому роутингу мы работали с двумя событиями, при этом использовали одни и те же обработчики. При необходимости мы можем добавлять новые события и не менять код обработчиков.

Выводы

В этом уроке мы разобрали, что такое роутинг — это процесс сопоставления HTTP-запроса с обработчиком, который будет обрабатывать этот запрос. Еще его называют маршрутизацией. Роутинг осуществляется с помощью путей и методов запроса, а динамический роутинг позволяет обрабатывать запросы с разными путями, и при этом использовать один обработчик.


Дополнительные материалы

  1. Fiber Routing

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»
Изображение Тото

Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу