在 HTTP 协议中,标头(Headers)是客户端和服务器之间交换的元数据,用于传递请求和响应的附加信息。Akka HTTP 是 Akka 生态系统中的一个模块,提供了基于 Reactive Streams 的 HTTP 服务器和客户端功能。
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.headers._
val route =
extractRequest { request =>
val headers = request.headers
complete(s"Received headers: ${headers.map(_.toString).mkString(", ")}")
}
headerValue
或 headerValueByName
提取特定标头val route =
headerValueByName("User-Agent") { userAgent =>
complete(s"Your User-Agent is: $userAgent")
} ~
headerValue(optionalHeaderValueByName("X-Custom-Header")) { customHeader =>
complete(s"Custom header value: ${customHeader.getOrElse("not present")}")
}
val route =
(headerValueByName("Authorization") & headerValueByName("Accept")) { (authToken, acceptHeader) =>
complete(s"Auth token: $authToken, Accept: $acceptHeader")
}
val route =
respondWithHeader(RawHeader("X-Custom-Header", "value")) {
complete("Response with custom header")
}
val route =
respondWithHeaders(
RawHeader("X-Custom-Header1", "value1"),
RawHeader("X-Custom-Header2", "value2"),
`Cache-Control`(`no-cache`)
) {
complete("Response with multiple headers")
}
Akka HTTP 预定义了许多常见标头类型:
Accept
Authorization
Content-Type
Cookie
Location
User-Agent
Cache-Control
Authorization
标头)Accept
标头)Cache-Control
标头)Origin
、Access-Control-*
标头)原因:HTTP 标头名称在规范上是不区分大小写的,但 Akka HTTP 的预定义标头类型使用特定的大小写格式。
解决方案:
headerValueByName
时,可以任意大小写原因:HTTP 允许某些标头出现多次(如 Set-Cookie
)
解决方案:
val route =
extractRequest { request =>
val cookies = request.headers[`Set-Cookie`]
complete(s"Found ${cookies.size} cookies")
}
原因:某些标头有特定格式要求(如 Authorization
)
解决方案:
val route =
optionalHeaderValueByType[Authorization]() {
case Some(auth) => complete(s"Auth scheme: ${auth.scheme}")
case None => complete("No Authorization header")
}
解决方案:
object `X-Custom-Header` extends ModeledCustomHeaderCompanion[`X-Custom-Header`] {
override def name = "X-Custom-Header"
override def parse(value: String) = Try(new `X-Custom-Header`(value))
}
final class `X-Custom-Header`(val value: String) extends ModeledCustomHeader[`X-Custom-Header`] {
override def companion = `X-Custom-Header`
override def renderInRequests = true
override def renderInResponses = true
}
val route =
headerValueByType[`X-Custom-Header`]() { customHeader =>
complete(s"Custom header value: ${customHeader.value}")
}
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.headers._
import scala.concurrent.ExecutionContextExecutor
import scala.io.StdIn
object MultiHeaderExample extends App {
implicit val system: ActorSystem = ActorSystem("multi-header-example")
implicit val executionContext: ExecutionContextExecutor = system.dispatcher
val route =
path("headers") {
get {
// 提取多个标头
(headerValueByName("User-Agent") &
optionalHeaderValueByType[Authorization]() &
extract(_.request.headers)) { (userAgent, authOpt, allHeaders) =>
// 添加多个响应标头
respondWithHeaders(
`Cache-Control`(`no-cache`),
RawHeader("X-Request-User-Agent", userAgent),
RawHeader("X-Total-Headers", allHeaders.size.toString)
) {
complete(
s"""
|User-Agent: $userAgent
|Authorization present: ${authOpt.isDefined}
|Total headers received: ${allHeaders.size}
|All headers: ${allHeaders.mkString("\n")}
""".stripMargin
)
}
}
}
}
val bindingFuture = Http().newServerAt("localhost", 8080).bind(route)
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
StdIn.readLine()
bindingFuture
.flatMap(_.unbind())
.onComplete(_ => system.terminate())
}
这个示例展示了如何:
没有搜到相关的文章