0Pricing
Scala for Backend Engineering & Functional Programming · 课时

请求与响应

读取输入并返回输出。

请求与响应 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 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]

构建响应

Ok、Created 和 NotFound 等 DSL 响应构造器会返回 F[Response[F]]。传入参数后,参数会通过 EntityEncoder 设置为请求体。

每个构造器对应一个状态码,因此 Created(...) 会产生 201。

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

直接设置状态码

如果某个状态没有便捷构造器,或者您需要进行自定义,可以使用明确的 Status 构造一个 Response[F],然后链接调用 withEntity。

这样,您可以在一个表达式中完全控制状态、标头和请求体。

import org.http4s.{Response, Status}

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

编码请求体

EntityEncoder[F, A] 会将值序列化为响应请求体,并设置 Content-Type。内置支持 String 和字节编码器;JSON 编码器来自 Circe。

当您将值传给 Ok(value) 时,http4s 会隐式查找相应的编码器。

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

设置响应标头

您可以将标头作为额外参数传给构造器,也可以在响应效果上链接调用 .map(_.putHeaders(...)) 来添加标头。

类型化标头模型可以确保值的格式正确,例如为 201 Created 响应设置 Location 标头。

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 与重定向

使用 response.addCookie(ResponseCookie(name, value)) 设置 Cookie。要执行重定向,请使用 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 和重定向都只是响应转换。

常见问题解答

「请求与响应」课时是免费的吗?

是的 — 「请求与响应」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

「请求与响应」这节课中我会学到什么?

读取输入并返回输出。 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 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