【问题标题】:Akka Http return 404 Not FoundAkka Http 返回 404 Not Found
【发布时间】:2016-08-26 08:39:33
【问题描述】:

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

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

/api/recipe/1

我想将资源作为 json 格式返回。

当我击中时

/api/recipe/2

应该返回 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)
        }
      }
    }
  }
}

更新

为了更清楚,这里是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 以使其能够返回 404 Not foundcomplete(Future[None[T]])

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

【问题讨论】:

  • getRecipeById的返回类型是什么?
  • Future[Option[Recipe]]
  • 那么,当您针对该 id 运行查询时会得到什么?你得到一个无吗?
  • 我只是一个简单的存根,如果 id 为 1,则返回 Some,否则返回 None。代码已添加到帖子中。
  • 您返回了两种不兼容的类型。您应该在范围内有一个隐式编组器。呼叫ToResponseMarshallable 是我在这里闻到的气味。编辑:我刚刚查看了我的一些 Akka-Http 代码...我返回了一个 StatusCode 元组 -> response 并且根本不使用 ToResponseMarshallable。

标签: scala http akka http-status-code-404 akka-http


【解决方案1】:

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

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

【讨论】:

  • 谢谢,我确实按照建议重构了代码。现在在Some 的情况下,我收到JSON 和200 OK,但在None 的情况下,我显然没有得到响应,但仍然是200 OK。现在我想知道这是否是 akka-http 中的默认设置,或者是否可以调整。
  • 请查看更新后的文本,rejectEmptyResponse 指令就是您所需要的。
猜你喜欢
  • 1970-01-01
  • 2016-03-16
  • 2021-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-01
  • 2017-06-08
相关资源
最近更新 更多