如何在 Akka Scala 的 HttpResponse 中设置 `Set-Cookie` header?

How to set `Set-Cookie` header in HttpResponse in Akka Scala?

我的应用程序中有以下路线:

val myRoute = Route { context =>

        val handler = Source.single(getRequest(context))
          .via(flow(server, port))
          .runWith(Sink.head).flatMap { r =>

          // Add cookie to response depending on certain preconditions

         context.complete(r)

      }

}

我的问题是我不能使用 out-of-the-box setCookie 方法(或者我可以吗?)因为我在路线内,所以我会收到类型错误。我考虑过手动向 HttpResponse 添加一个 header 元素(在上面的示例中 r),但这很麻烦。

知道如何轻松添加 Set-Cookie header 元素吗?

setCookie 指令

A Route 就是 a type definition: (RequestContext) => Future[RouteResult]。因此,您可以使用函数组合将 cookie 添加到来自下游服务的 HttpResponse

首先创建一个使用预定义流的转发器:

val forwardRequest : HttpRequest => Future[HttpResponse] = 
  Source
    .single(_)
    .via(flow(server, port))
    .runWith(Sink.head)

然后用 getRequest 和一个从 HttpResponseRouteResult 的转换器组成该函数:

val queryExternalService : Route = 
  getRequest andThen forwardRequest andThen (_ map RouteResult.Complete)

最后,设置cookie:

val httpCookie : HttpCookie = ??? //not specified in question

val myRoute : Route = setCookie(httpCookie)(queryExternalService)

路线中的手动补遗

您可以手动设置cookie:

val updateHeaders : (HttpHeader) => (HttpResponse) => HttpResponse = 
  (newHeader) => 
    (httpResponse) => 
      httpResponse withHeaders {
        Some(httpResponse.headers.indexWhere(_.name equalsIgnoreCase newHeader.name))
          .filter(_ >= 0)
          .map(index => httpResponse.headers updated (index, newHeader) )
          .getOrElse( httpResponse.headers +: newHeader )
      }
...
.runWith(Sink.head).flatMap { response =>
  context complete updateHeaders(httpCookie)(response)
}

纯流量

您甚至可以通过将 Flow 传递给 HttpExt#bindAndHandle 来完全避免使用路由:

val myRoute : Flow[HttpRequest, HttpResponse, _] = 
  flow(server,port) map updateHeaders(httpCookie)