找不到Akka Http返回404

Dav*_*iro 1 scala http akka http-status-code-404 akka-http

我正在努力实现非常简单的事情。

说,我有一个REST API。当我打电话

/api/recipe/1
Run Code Online (Sandbox Code Playgroud)

我想将一种资源作为json返回。

当我打

/api/recipe/2
Run Code Online (Sandbox Code Playgroud)

404 Not Found HTTP响应应返回。就那么简单。

显然,我缺少关于路由指令如何工作的信息,因为我无法将它们组成以遵守上述逻辑。

不幸的是,我找不到任何具体示例,官方文档也没有特别帮助。

我正在尝试类似的操作,但是代码给出了编译错误:

class RecipeResource(recipeService: RecipeService)(implicit executionContext: ExecutionContext) extends DefaultJsonProtocol {

  implicit val recipeFormat = jsonFormat1(Recipe.apply)

  val routes = pathPrefix("recipe") {
    (get & path(LongNumber)) { id =>
      complete {
        recipeService.getRecipeById(id).map {
          case Some(recipe) => ToResponseMarshallable(recipe)
          // type mismatch here, akka.http.scaladsl.marshalling.ToResponseMarshallable 
          // is required
          case None => HttpResponse(StatusCodes.NotFound)
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

更新资料

以下是recipeService更清晰的代码:

class RecipeService(implicit executionContext: ExecutionContext) {

  def getRecipeById(id: Long): Future[Option[Recipe]] = {
    id match {
      case 1 => Future.successful(Some(Recipe("Imperial IPA")))
      case _ => Future.successful(None)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我得到的编译错误:

[error] /h......../....../...../RecipeResource.scala:22: type mismatch;
[error]  found   : scala.concurrent.Future[Object]
[error]  required: akka.http.scaladsl.marshalling.ToResponseMarshallable
[error]         recipeService.getRecipeById(id).map {
[error]                                             ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
Run Code Online (Sandbox Code Playgroud)

更新2

基于leachbj的答案,我摆脱了路由中不必要的模式匹配。现在,代码进行编译,如下所示:

class RecipeResource(recipeService: RecipeService)(implicit executionContext: ExecutionContext) extends DefaultJsonProtocol {

  implicit val recipeFormat = jsonFormat1(Recipe.apply)

  val routes = pathPrefix("recipe") {
    (get & path(LongNumber)) { id =>
      complete(recipeService.getRecipeById(id))
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

当配方存在时(例如/api/recipe/1),我得到JSON响应和200 OK,这是预期的。

现在,在资源不存在的情况下(例如/api/recipe/2),响应为空,但200 OK接收到状态码。

我的问题是,如何调整akka-http才能complete(Future[None[T]])返回404 Not found

我正在寻找一种适用于任何Future[None]返回值的通用方法。

lea*_*hbj 6

如果您complete(Future[Option[T]])并且有合适的Json Marshaller可用,则Akka将返回响应作为json(如果值为)Some(v)或的空200响应None。如果使用spray-json,则创建一个RootJsonFormat[T]隐式对象并添加import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._。其他编组库也有类似的支持隐式。

要为None您生成404,需要complete使用rejectEmptyResponse指令包装。