Реализация веб-сервиса с помощью Go и Fiber
20 октября 2022 г.Принципы веб-разработки одинаковы для всех веб-фреймворков. Давайте изучим основы веб-разработки с помощью языка программирования Go и фреймворка Fiber и напишем самый простой веб-сервис.
Какие причины существования фреймворков?
Каждый популярный веб-сервис основан на обмене данными между клиентами и серверами. Постоянно повторяющаяся обработка запросов и возврат ответов включает в себя множество элементов, аналогичных большинству сайтов.
Мы не хотим разрабатывать аналогичные инструменты для каждого нового сайта. Мы хотим создавать повторно используемые инструменты для похожей логики, а не изобретать каждый раз что-то новое. Фреймворки были разработаны для этих целей. Они включали механизмы для стандартных вопросов веб-разработки. Благодаря фреймворкам мы не можем быстрее решать бизнес-задачи и практически пропускать низкоуровневые технические вопросы.
Запросы и ответы
Большинство современных веб-фреймворков основаны на парадигме ответ-запрос и не зависят от языка программирования и особенностей реализации.
Давайте реализуем самый простой веб-сервер с фреймворком Fiber, чтобы понять его внешний вид. Файбер минималистичный, но быстрый и содержит все необходимые инструменты для реализации. Инструкции по установке можно найти на сайте.
Привет, мир!
Давайте напишем простейшее приложение с помощью Fiber. Традиционно это будет веб-сервер, который возвращает Hello, World! Создайте файл server.go
со следующим содержимым:
package main
import "github.com/gofiber/fiber/v2"
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Listen(":3000")
}
Запустите приложение с помощью команды в терминале
go run server.go
В браузере введите http://localhost:3000 и увидите текст Hello, World!
Давайте разберем приложение и посмотрим, как сервер понимает, что делать, и в то же время познакомимся с одним важным понятием: маршрутизацией.
- В этом фрагменте кода мы создаем пакет с именем
main
. В каждом пакете Go есть функцияmain
, и наш код не исключение. - Импортируйте необходимый модуль инфраструктуры Fiber.
- В начале функции
main
мы создаем новый экземпляр нашего веб-сервера. Он будет обслуживать запросы и выполнять работу. - Следующий шаг — обработка маршрута /. Интернет-запросы имеют адрес или URL. Нам не нужен порт или домен, если мы уже внутри сервера, чтобы отправить наш запрос на обработку. Нам нужен только путь от исходного адреса и метод, используемый в запросе.
- Мы рассмотрим другие параметры более подробно позже, а пока предположим, что сервер будет обрабатывать запрос GET с кратчайшим путем / и отправлять строку в ответ, используя Контекстный метод
SendString
. - В функцию-обработчик передается параметр с указателем на структуру контекста. Хотя дизайн и советы специфичны для нашей платформы, понятие контекста, связанного с запросом, является универсальным. Контекст запроса содержит необходимую информацию и методы для обработки текущего запроса.
- Компоненты объектов ответа и запроса — заголовки с метаинформацией
- В последней строке нашей функции
main
мы указываем, какой порт сервера будет обрабатываться. Здесь 3000, но подойдет любой порт. Вы можете запускать несколько экземпляров одного и того же сервера на разных портах.
Обработку запроса мы написали на /, а как дальше идти и обрабатывать остальные запросы. В конце концов, мы хотим, чтобы наш сервер мог делать что-то еще.
Более сложный обработчик
Каждый запрос, поступающий на сервер, имеет адрес. Для нашего сервера, пока он работает локально на нашей машине, адрес выглядит так: http://localhost:3000/resource. Браузер уже знает, что наш сервер работает по адресу localhost:3000, поэтому мы не обрабатываем эту часть внутри, а обрабатываем часть ресурсов. Если мы отправляем запрос из адресной строки браузера — используется метод GET, поэтому внутри нашего фреймворка мы повторяем обработчик адреса /, который у нас уже есть. Это будет выглядеть так:
app.Get("/resource", func(c *fiber.Ctx) error {
return c.SendString("Desired resource")
})
Перезапускаем сервер, и, введя ссылку в браузере, получаем результат - строку Желаемый ресурс.
Как видно из примера, первый параметр функции с именем метода HTTP-запроса отвечает за обработку определенного пути в Файбере. Функция-обработчик, указанная вторым параметром, отвечает за результат, возвращаемый по конкретному запросу. Сопоставление пути и обработчика на веб-сервере называется маршрутизацией и является обязательным шагом в каждой веб-инфраструктуре.
Динамический адрес
Адреса могут быть динамическими и содержать такие параметры, как идентификатор пользователя или название фильма. Внутри Fiber также есть готовый функционал для этого. Давайте реализуем обработчик запросов со следующим параметром http://localhost:3000/resource/resource_id
.app.Get("/resource/:id", func(c *fiber.Ctx) error {
return c.SendString("Desired resource = " + c.Params("id"))
})
Двоеточие перед именем параметра позволит нам получить это значение в обработчике запроса, что мы и демонстрируем, добавляя идентификатор ресурса в ответ. Может быть более одного параметра, что позволяет реализовать сложную маршрутизацию.
Вот что такое маршрут и обработчик запросов с двумя параметрами http://localhost:3000/user/8427/book/HarryPotterandtheChamberofSecrets< /a> будет выглядеть так:
app.Get("/user/:id/book/:title", func(c *fiber.Ctx) error {
return c.SendString("Desired book is " + c.Params("title") + " from user " + c.Params("id"))
})
Параметры запроса
Помимо включения параметров непосредственно в путь запроса, переменные заменяются в параметрах запроса. Вы, наверное, видели такие URL-адреса, как http://localhost:3000/book_cover?size=140x200&filename=cover .png Параметры в URL-адресах в основном используются для указания идентификатора объекта или имени, а параметры запроса используются для передачи любой информации. Это хорошо зарекомендовавшая себя практика, но ничто не помешает вам передать что-либо в качестве параметра URL.
Конечно, существуют ограничения по длине — многие веб-сервисы не допускают очень длинных URL-адресов. Если вам нужно много данных, вы должны использовать запрос POST и передавать параметры не в URL, а в теле запроса. Ниже давайте посмотрим код для обработки параметра запроса. Функция контекста Query
используется для получения параметра из запроса.
app.Get("/book_cover", func(c *fiber.Ctx) error {
return c.SendString("Desired book cover has size " + c.Query("size") + " with filename " + c.Query("filename"))
})
Пересохраняем код, и после вызова нашего URL получаем параметры из запроса в ответ. Очень важно получить параметры в обработчике и убедиться, что они имеют правильный формат и значения. Этот шаг называется проверкой.
Структура запроса
В обработчике откройте структуру запроса и просмотрите необходимую информацию. Fiber скрывает работу с методом запроса и настраивает маршрутизацию без усилий с нашей стороны. Вы можете получить метод напрямую следующим образом:
app.Get("/", func(c *fiber.Ctx) error {
c.Request().Header.Method()
// => []byte("GET")
})
Как видим, контекстный метод Request
вернет всю необходимую информацию.
Структура ответа
Если в контексте есть объект запроса, очевидно, что есть и объект ответа. К нему также часто требуется доступ. Сценарии использования разнообразны: вернуть тип возвращаемого ответа, сохранить ключ для хеширования и добавить информацию об авторизации. Эти данные записываются в заголовки ответа. Однако вы не должны возвращать файлы в заголовках, и также есть ограничение по размеру.
Fiber содержит полезные методы, которые скрывают необработанный ответ, но объект ответа доступен, если вы хотите, как показано в следующем фрагменте кода:
// GET http://localhost:3000/custom_header
app.Get("/custom_header", func(c *fiber.Ctx) error {
c.Response().Header.Set("X-My-Header", "my-header-value")
return c.SendString("Hello, World!")
})
Если вы запросите URL-адрес в браузере, вы получите стандартный ответ Hello, World!. Вы можете увидеть заголовки в консоли разработчика или с помощью таких инструментов, как cUrl или Postman.
Заключение
Сегодня мы рассмотрели несколько концепций разработки веб-приложений. Тем не менее, стоит еще раз вспомнить — независимо от языка программирования и фреймворка вам придется работать с HTTP-запросами.
Вы сами выбираете, добавлять ли параметры непосредственно в URL-адрес или добавлять их в качестве параметров запроса. Сделать запросы GET или POST и что добавить или удалить из заголовков. Если вы хотите использовать язык программирования Go и фреймворк Fiber, вам помогут готовые примеры из сегодняшнего урока.
Полезные ссылки
Весь список
Весь код приложения из текущей статьи прикреплен ниже:
package main
import "github.com/gofiber/fiber/v2"
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Get("/resource", func(c *fiber.Ctx) error {
return c.SendString("Desired resource")
})
app.Get("/resource/:id", func(c *fiber.Ctx) error {
return c.SendString("Desired resource = " + c.Params("id"))
})
app.Get("/user/:id/book/:title", func(c *fiber.Ctx) error {
return c.SendString("Desired book is " + c.Params("title") + " from user " + c.Params("id"))
})
app.Get("/bookfile", func(c *fiber.Ctx) error {
return c.SendString("Desired bookfile has size " + c.Query("size") + " with filename " + c.Query("filename"))
})
app.Get("/custom_header", func(c *fiber.Ctx) error {
c.Response().Header.Set("X-My-Header", "my-header-value")
return c.SendString("Hello, World!")
})
app.Listen(":3000")
}
Оригинал