16

Future で Option[ProductDoc] を返すサービスがあります (akka ask として)

スプレー ルーティングで、有効な製品は製品に応答するが、不明だが適切に形成された製品は 404 を返すようにするにはどうすればよいですか?

コードでここのギャップを埋めたい:

get {
    path("products" / PathElement) { productID:String =>
      val productFuture = (productService ? ProductService.Get(productID)).mapTo[Option[ProductDoc]]

      // THE CODE THAT GOES HERE SO THAT
      // IF PRODUCT.ISDEFINED RETURN PRODUCT ELSE REJECT

    }
}

私が仕事に取り掛かることができる唯一の方法は、この忌まわしきものです:

get {
    path(PathElement) { productID:String =>
      val productFuture = (productService ? ProductService.Get(productID)).mapTo[Option[ProductDoc]]
      provide(productFuture).unwrapFuture.hflatMap {
        case x => provide(x)
      } { hResponse:shapeless.::[Option[ProductDoc], HNil] =>
        hResponse.head match {
          case Some(product) => complete(product)
          case None => reject
        }
      }
    }
  }

これは、これを達成するための正しい方法ではありませんよね? これはかなり単純なパターンのように思えますが、すでに誰かによって解決されているはずです!

4

2 に答える 2

17

スプレーはあなたのユースケースをすでにサポートしています: オプション値Noneはデフォルトで にマーシャリングさEmptyEntityれます。これはおそらく、変更を加える前に表示されていたものです: 空のドキュメントを持つ 200 です。空のドキュメントを 404 に変換するディレクティブがありrejectEmptyResponseます。この動作が必要なルートの部分をラップします。

ルートは次のようになります。

  rejectEmptyResponse {
    path("products" / PathElement) { productID:String =>
      val productFuture = // same as before
      complete(productFuture)
    }
  }

もちろん、rejectEmptyResponseより多くのルート パーツをラップするかどうかに応じて、パスの内側に配置することもできます。

より詳しい情報:

于 2013-03-12T09:23:09.107 に答える
0

私は数日前に同じ問題を抱えており、この解決策にたどり着きました:

このメソッドをアクターに追加しました

def failIfEmpty[T](item: Future[Option[T]], id: String) = {
    (item map {
      case Some(t) => t
      case None => throw NotFoundException(Message(s"id '$id' could not be        found",`ERROR`))
    }) pipeTo sender
}

もちろん、好きな例外を選択できます。NotFoundException は私自身のものです...

結果に対してこれを呼び出して、アクターからの質問に答えます (これは ReactiveMongo を使用する例です。あなたの に置き換えcollection.find(query).headOptionてくださいFuture[Option]):

failIfEmpty(collection.find(query).headOption, id)

次に、次のように ExceptionHandler をサービス (ルートが定義されている場所) に追加します。

implicit val klaraExceptionHandler = ExceptionHandler.fromPF {
    case InternalServerErrorException(messages) => complete(InternalServerError, messages)
    case NotFoundException(message) => complete(NotFound, message)
    case ValidationException(messages) => complete(PreconditionFailed, messages)
    [and so on]
}

このようにして、将来の結果で発生するいくつかの異なるエラーを処理できます。

于 2013-03-12T08:07:13.117 に答える