Веб-разработка на Go

Теория: Веб-приложение на микрофреймворке Fiber

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

В этом уроке разберем микрофреймворк Fiber. Мы расскажем, чем он помогает разработчикам и как на нем реализовать веб-приложение.

Что такое микрофреймворк Fiber

Схема работы веб-приложения выглядит следующим образом:

  1. Разбор входящих запросов
  2. Поиск обработчика по пути запроса
  3. Выполнение логики обработчика
  4. Формирование и отправка ответа

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

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

Микрофреймворк ценится программистами, так как упрощает разработку. Поэтому важно разобраться, как на нем реализуется веб-приложение.

Как реализовать веб-приложение на Fiber

Посмотрим, как Fiber упрощает реализацию веб-приложения. Представим, что у нас есть страница с адресом компании:

package main

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

func main() {
	webApp := fiber.New()
	// Обозначаем, что на GET запрос по пути /address нужно вернуть строку с адресом
	webApp.Get("/address", func(c *fiber.Ctx) error {
		return c.SendString("145 DUNDEE SOUTH SAN FRANCISCO CA 94080-1023. USA")
	})

	// Запускаем веб-приложение на порту 80
	// Оборачиваем в функцию логирования, чтобы видеть ошибки, если они возникнут
	logrus.Fatal(webApp.Listen(":80"))
}

Запускаем веб-приложение, открываем браузер и переходим на страницу http://localhost/address — получаем в ответ строку "145 DUNDEE SOUTH SAN FRANCISCO CA 94080-1023. USA".

Разберем, как данный пример ложится на общую схему работы веб-приложений:

  1. Разбор входящих запросов
  2. Поиск обработчика по пути запроса

Эти пункты выполняются в следующей строке:

webApp.Get("/address", func (c *fiber.Ctx) error {

Здесь обработчик должен вызваться при получении GET запроса по пути "/address". При этом логика, где разбирается запрос и сопоставляются пути с обработчиком, находится в микрофреймворке Fiber, а мы используем готовые функции.

Следующие два шага:

  1. Выполнение логики обработчика
  2. Формирование и отправка ответа

В примере выше эти пункты тоже описываются одной строкой:

return c.SendString("145 DUNDEE SOUTH SAN FRANCISCO CA 94080-1023. USA")

Большую часть времени веб-разработчики пишут код внутри обработчиков. При этом используют готовые библиотеки для удобства и эффективности. В нашем примере не нужно писать низкоуровневый код по передаче байт в сетевом соединении для ответа. Мы вызываем функцию из Fiber c.SendString(), которая сделает всё за нас.

Теперь мы знаем, как реализовать веб-приложение на Fiber. Он заметно упрощает разработку, так как готовые библиотеки с функциями частично выполняют работу программиста.

Упрощенно логика обработчика выглядит так: прочитай запрос и отдай ответ. Поэтому важно знать, как работать с запросами и ответами в используемом микрофреймворке. Рассмотрим, как это делается в Fiber.

Как работать с запросами и ответами в Fiber

В стандартном пакете net/http запрос и ответ разделены в разные структуры. В Fiber все нужное содержится в одной структуре *fiber.Ctx. Если использовать ее, можно читать параметры и тело запроса, а также отправлять любые ответы.

Разберем работу с запросом и ответом в Fiber на примере. Представим, что нам нужно реализовать веб-приложение, у которого есть страница с профилями пользователей. Когда программа получает профиль, передается его идентификатор с помощью GET параметра profile_id.

Если profile_id не указан, то приложение должно возвращать ответ со статусом 422 (Unprocessable Entity) и текстом ошибки в теле. Если передается корректный profile_id, то возвращается строка с идентификатором профиля:

package main

import (
	"fmt"

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

const profileUnknown = "unknown"

func main() {
	webApp := fiber.New()
	webApp.Get("/profiles", func(c *fiber.Ctx) error {
		profileID := c.Query("profile_id", profileUnknown)
		if profileID == "" {
			profileID = profileUnknown
		}

		if profileID == profileUnknown {
			return c.Status(fiber.StatusUnprocessableEntity).SendString("profile_id is required")
		}

		return c.SendString(fmt.Sprintf("User Profile ID: %s", profileID))
	})

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

Запускаем веб-приложение, открываем браузер и переходим на страницу http://localhost/profiles — получаем в ответ строку ошибки "profile_id is required".

Попробуем передать корректный идентификатор профиля. Переходим по ссылке http://localhost/profiles?profile_id=300 — получаем в ответ строку "User Profile ID: 300".

Разберем подробнее код обработчика из данного примера.

По описанию веб-приложения от нас требовалось считывать GET параметр с идентификатором профиля. Это происходит в этой строке:

profileID := c.Query("profile_id", profileUnknown)

Запросы, которые приходят на сервер, не всегда корректны. Поэтому profile_id может быть не указан или передан пустым значением. Мы обрабатываем такое ошибочное поведение и возвращаем ошибку:

if profileID == "" {
    profileID = profileUnknown
}

if profileID == profileUnknown {
    return c.Status(fiber.StatusUnprocessableEntity).SendString("profile_id is required")
}

Если получаем корректное значение profile_id, то возвращаем его в ответе:

return c.SendString(fmt.Sprintf("User Profile ID: %s", profileID))

В итоге у нас получилось считать GET-параметры запроса и отправить ответы с помощью микрофреймворка Fiber.

Выводы

  • Веб-приложения работают одинаково, поэтому разработчики используют микрофреймворки. С их помощью не нужно писать один и тот же код, чтобы обработать запросы
  • Fiber — один из популярных микрофреймворков на Go с интуитивными функциями и высокой производительностью
  • Обработчика на GET HTTP-запросы настраивают через вызов функции Get("/path", func(c *fiber.Ctx) error {})
  • Вся информация о HTTP-запросе находится в структуре c *fiber.Ctx
  • Чтобы написать ответ, необходимо вызвать функцию c.SendString() у объекта контекста Fiber. При этом можно предварительно указать код статуса ответа функцией c.Status()

Рекомендуемые программы