0Pricing
Scala for Backend Engineering & Functional Programming · Урок

Запросы и ответы

Читайте входные данные и возвращайте результат.

«Запросы и ответы» — бесплатный урок Scala for Backend Engineering & Functional Programming на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Scala for Backend Engineering & Functional Programming, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.

Запрос как значение

В http4s Request[F] — это неизменяемое значение, содержащее метод, URI, заголовки, версию HTTP и потоковое тело. Вы изучаете его с помощью чистых средств доступа и никогда не изменяете на месте.

Чтобы изменить запрос, создайте его копию с помощью withHeaders, withUri или похожих комбинаторов.

val r: Request[IO] = Request[IO](
  method = Method.GET,
  uri = uri"/health"
)

Потоковое тело

Тело запроса или ответа — это fs2.Stream[F, Byte]. Оно потребляется лениво и с использованием эффектов, поэтому большие полезные нагрузки не требуется полностью хранить в памяти.

Обычно вам не приходится работать с необработанными байтами: EntityDecoder выполняет декодирование за вас.

// raw access (rarely needed)
val bytes: fs2.Stream[IO, Byte] = request.body

Декодирование тела

EntityDecoder[F, A] умеет преобразовывать поток тела в A. Вызовите req.as[A] для декодирования: он возвращает F[A] и завершается ошибкой эффекта, если тело имеет неверный формат.

Для String существует встроенный декодировщик; более содержательные декодировщики предоставляются модулями JSON.

HttpRoutes.of[IO] {
  case req @ POST -> Root / "echo" =>
    req.as[String].flatMap(body => Ok(body))
}

Привязка запроса

Чтобы получить доступ к объекту запроса внутри случая, свяжите его с помощью @. Здесь req обозначает весь запрос, а шаблон по-прежнему сопоставляет метод и путь.

Без связывателя доступны только разобранные части, поэтому прочитать тело или заголовки невозможно.

HttpRoutes.of[IO] {
  case req @ PUT -> Root / "name" =>
    req.as[String].flatMap(n => Ok(s"set $n"))
}

Чтение заголовков

Заголовки находятся в request.headers. Используйте headers.get[H] с типизированной моделью заголовка или headers.get(CIString("X-Custom")) для произвольных имён.

Типизированные заголовки, такие как Authorization и Content-Type, самостоятельно разбирают и проверяют свои значения.

import org.http4s.headers.Authorization

val auth: Option[Authorization] =
  request.headers.get[Authorization]

Создание ответов

Средства DSL для построения ответов, такие как Ok, Created и NotFound, являются функциями, возвращающими F[Response[F]]. Передача аргумента задаёт тело через EntityEncoder.

Каждое такое средство соответствует коду состояния, поэтому Created(...) возвращает 201.

Ok("all good")          // 200
Created("made it")      // 201
NotFound("missing")     // 404

Прямое указание кодов состояния

Если для нужного состояния нет готового средства или требуется настройка, создайте Response[F] с явным Status и добавьте withEntity.

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

import org.http4s.{Response, Status}

Response[IO](Status.Accepted)
  .withEntity("queued")
  .pure[IO]

Кодирование тел

EntityEncoder[F, A] сериализует значение в тело ответа и устанавливает Content-Type. Кодировщики строк и байтов встроены; кодировщики JSON предоставляются Circe.

Когда вы передаёте значение в Ok(value), http4s неявно находит подходящий кодировщик.

// String encoder is implicit; sets text/plain
val resp: IO[Response[IO]] = Ok("plain text body")

Установка заголовков ответа

Добавляйте заголовки, передавая их как дополнительные аргументы средству построения ответа, или применяйте .map(_.putHeaders(...)) к эффекту ответа.

Типизированные модели заголовков обеспечивают правильный формат значений, например заголовка Location для ответа 201 Created.

import org.http4s.headers.Location

Created("ok").map(_.putHeaders(
  Location(uri"/items/42")
))

Обработка ошибок декодирования

req.as[A] завершает эффект F ошибкой, если тело невозможно декодировать. Используйте req.attemptAs[A].value, чтобы получить F[Either[DecodeFailure, A]] и вернуть 400 при результате слева.

Так обработка неверных входных данных остаётся явной и тотальной.

req.attemptAs[String].value.flatMap {
  case Right(b) => Ok(b)
  case Left(_)  => BadRequest("bad body")
}

Файлы cookie и перенаправления

Устанавливайте файлы cookie с помощью response.addCookie(ResponseCookie(name, value)). Для перенаправлений используйте средство построения ответа класса 3xx и заголовок Location.

SeeOther(Location(uri)) выполняет перенаправление 303 — идиоматичный ответ после отправки формы с переходом на получение результата.

import org.http4s.headers.Location

SeeOther(Location(uri"/login"))
  .map(_.addCookie("sid", "abc123"))

Быстрая проверка

Подумайте о безопасном декодировании тела.

Итоги

Запросы и ответы — это неизменяемые значения с потоковыми телами fs2. Вы декодируете их с помощью as/attemptAs через EntityDecoder, а кодируете с помощью EntityEncoder.

Сборщики задают коды состояния, типизированные заголовки остаются безопасными, а файлы cookie и перенаправления — это всего лишь преобразования ответов.

Часто задаваемые вопросы

Урок «Запросы и ответы» бесплатный?

Да — полный текст урока «Запросы и ответы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Scala for Backend Engineering & Functional Programming, подпишись на CoddyKit PRO. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.

Чему я научусь в уроке «Запросы и ответы»?

Читайте входные данные и возвращайте результат. Ты практикуешь Scala for Backend Engineering & Functional Programming с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Scala for Backend Engineering & Functional Programming?

Предыдущий опыт не требуется. Scala for Backend Engineering & Functional Programming на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Запросы и ответы»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Scala for Backend Engineering & Functional Programming?

Да. Каждый урок Scala for Backend Engineering & Functional Programming включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Маршруты и HttpRoutes
  2. Запросы и ответы
  3. Конечные точки JSON
  4. Предоставление приложения
← Назад к Scala for Backend Engineering & Functional Programming