Akka Http return 404 未找到

Akka Http return 404 Not Found

我正在尝试实现非常简单的事情。

说,我有 REST API。当我打电话时

/api/recipe/1

我想将资源作为 json 进行 returned。

当我打

/api/recipe/2

404 Not Found HTTP 响应应该 returned。就这么简单。

很明显,我遗漏了一些关于路由指令如何工作的信息,因为我无法将它们组合成符合上述逻辑的内容。

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

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

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)
        }
      }
    }
  }
}

更新

为了更清楚起见,这里是 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)
    }
  }
}

我得到的编译错误:

[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

更新 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))
    }
  }
}

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

现在,如果资源不存在(例如 /api/recipe/2),响应为空,但会收到 200 OK 状态代码。

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

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

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

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