简体   繁体   English

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

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

I have the following route in my app: 我的应用中有以下路线:

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)

      }

}

My problem is that I can't use the out-of-the-box setCookie method (or can I?) because I am inside a route, so I will get a type error. 我的问题是我不能使用现成的setCookie方法(或者可以吗?),因为我在路由内,所以会出现类型错误。 I thought about manually adding a header element to the HttpResponse (in the example above r ), but that is quite cumbersome. 我考虑过手动将标头元素添加到HttpResponse (在r上面的示例中),但这很麻烦。

Any ideas how I can easily add the Set-Cookie header element? 有什么想法可以轻松添加Set-Cookie标头元素吗?

setCookie Directive setCookie指令

A Route is just a type definition : (RequestContext) => Future[RouteResult] . Route只是类型定义(RequestContext) => Future[RouteResult] Therefore you can use function composition to add a cookie to the HttpResponse coming from the downstream service. 因此,您可以使用函数组合将cookie添加到来自下游服务的HttpResponse

First create a forwarder that utilizes the predefined flow: 首先创建一个使用预定义流程的转发器:

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

Then compose that function with getRequest and a converter from HttpResponse to RouteResult : 然后使用getRequest和从HttpResponseRouteResult的转换器组成该函数:

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

Finally, set the cookie: 最后,设置cookie:

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

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

Manual Addendum in Route 路线中的手册附录

You can manually set the cookie: 您可以手动设置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)
}

Pure Flow 纯流量

You can even avoid using Routes altogether by passing a Flow to HttpExt#bindAndHandle : 您甚至可以通过将Flow传递给HttpExt#bindAndHandle来完全避免使用Routes:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM