Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Akka:如何将消息内容包装成HTTP响应?_Scala_Akka_Akka Http - Fatal编程技术网

Scala Akka:如何将消息内容包装成HTTP响应?

Scala Akka:如何将消息内容包装成HTTP响应?,scala,akka,akka-http,Scala,Akka,Akka Http,在我的Akka http路由中,我收到一条特定的消息,我想将其内容包装为错误消息,如: val response:Future[T] = (actor ? command).mapTo[T] response match { case err : Future[InvalidRequest] => HttpResponse(408, entity = err.map(_.toJson).????) case r : Future[T]

在我的Akka http路由中,我收到一条特定的消息,我想将其内容包装为错误消息,如:

val response:Future[T] = (actor ? command).mapTo[T]
    response match {
      case err : Future[InvalidRequest] => 
          HttpResponse(408, entity = err.map(_.toJson).????)
      case r : Future[T] => r.map(_.toJson)
    }

case class InvalidRequest(error:String)

implicit val invalidRequestFormat = jsonFormat1(InvalidRequest)

但这不起作用。如何将其映射为json格式的文本?

我想我可以为您正在尝试的内容提供一个通用的解决方案。您可以创建一个返回
路由的方法,如下所示:

def service[T:ClassTag](actor:ActorRef, command:Any)
 (implicit timeout:Timeout,  _marshaller: ToResponseMarshaller[T]):Route = {
  val fut = (actor ? command).mapTo[ServiceResponse]
  onComplete(fut){
    case util.Success(ir:InvalidRequest) =>
      complete(StatusCodes.BadRequest, ir)

    case util.Success(t:T) =>
      complete(t)

    case util.Failure(ex) =>
      complete(StatusCodes.InternalServerError )        
  }    
}
val routes:Route = {
  path("api" / "foo"){
    get{
      service[Foo](fooActor, FooActor.DoFoo)
    }
  }  
}
此方法通过ask向提供的参与者发出请求,并获取表示结果的
Future
。然后,它使用
onComplete
指令对
InvalidResponse
案例应用特殊处理。这里很重要的一点是,在范围内有一个隐式的
响应器[T]
,因为成功案例需要它

然后,假设您定义了以下类和格式化程序:

trait ServiceResponse
case class Foo(id:Int) extends ServiceResponse
implicit val fooFormat = jsonFormat1(Foo)
case class InvalidRequest(error:String) extends ServiceResponse
implicit val invalidRequestFormat = jsonFormat1(InvalidRequest)
您可以在路由树中使用新的
服务
方法,如下所示:

def service[T:ClassTag](actor:ActorRef, command:Any)
 (implicit timeout:Timeout,  _marshaller: ToResponseMarshaller[T]):Route = {
  val fut = (actor ? command).mapTo[ServiceResponse]
  onComplete(fut){
    case util.Success(ir:InvalidRequest) =>
      complete(StatusCodes.BadRequest, ir)

    case util.Success(t:T) =>
      complete(t)

    case util.Failure(ex) =>
      complete(StatusCodes.InternalServerError )        
  }    
}
val routes:Route = {
  path("api" / "foo"){
    get{
      service[Foo](fooActor, FooActor.DoFoo)
    }
  }  
}

您的示例的问题在于,在构建响应之前,您没有等待
未来的完成。您试图匹配的是
Future
的底层类型,该类型在运行时通过擦除消除,因此尝试以这种方式进行匹配不是一个好主意。相反,您需要等待它完成,然后查看
未来的
后面的类型

您是否使用Akka的spray json支持来封送到json?是的,我已经更新了问题。我认为尝试将http状态更改为408Thank you可能会更容易。我使用的是Akka 2.4.7,
complete
的唯一有效签名是
def complete(m:⇒ ToResponseMarshallable)
因此我无法注入状态。@随机化,有没有可能升级到Akka 2.4.8?是的,我做到了。然而,它只是这样做:
complete(StatusCodes.BadRequest,ir.error)