Запросы и ответы
Читайте входные данные и возвращайте результат.
«Запросы и ответы» — бесплатный урок 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 — локальная установка не требуется.