2016-01-05 22 views
5

Akka Httpルーティングシステムとその拒否システムを使用したいが、一般的なJsonメッセージブロック内の拒否に対して応答Jsonをネストする必要がある。Akka-Httpで拒否を包括的に包む方法

これは非常に非汎用的な方法でRejectionHandlerを作成し、すべての可能性のある拒否に対してケースを追加し、すべてを特定のレスポンスコードとメッセージで処理します。

例:

// Wraps string into control block format 
def WrappingBlock(msg: String) = ??? 

val myRejectionHandler = RejectionHandler 
.newBuilder() 
.handle{case MalformedRequestContentRejection(msg, detail) => 
      complete(BadRequest, WrappingBlock(msg)) } 
...  // Further lines for all other possible rejections 
...  // along with their response codes and messages. 
...  // It would be nice if this was just generic code 
...  // rather than specific to every rejection type. 
.result() 


val routes = handleRejections(myRejectionHandler){ 
    ... 
} 

しかし、私が希望するアッカHTTPがデフォルトで提供応答コードともただの行せずにJSON制御ラッパー内にネスト提供され、かなりの印刷メッセージであります可能なすべての拒否タイプ。これは可能なはずだが、私はそれを完了することができなかったようだ。

答えて

5

私はそれはあなたがmapResponseで明示的にhandleRejectionsの組み合わせを使用してやりたいことも可能だと思います。私はJSONを使用して応答しますと、彼らはJSONとしてレスポンスを解析することができますので、私の呼び出し側が満足しているマッチング要求を取得した場合

​​

:まず、この単純なルート定義を考えます。しかし、あなたはPOSTリクエストで、このエンドポイントを試してみて呼び出した場合、次のように、あなたが応答を取得します:

HTTP 405 Method Not Allowed 

Date: Wed, 06 Jan 2016 13:19:27 GMT 
Content-Type: text/plain; charset=UTF-8 
Content-Length: 47 
Allow: GET 
Server: akka-http/2.3.12 

HTTP method not allowed, supported methods: GET 

そこでここでは、望ましくないプレーンテキストの応答を取得します。私たちは、そのように私のルーティングツリーの最上部にディレクティブのカップルを追加することによって、普遍その問題を解決することができます:wrapToJson

mapResponse(wrapToJson){ 
    handleRejections(RejectionHandler.default){ 
    (get & path("foo")){ 
     complete((StatusCodes.OK, HttpEntity(ContentTypes.`application/json`, """{"foo": "bar"}"""))) 
    } 
    } 
} 

は以下のように定義されている:

def wrapToJson(resp:HttpResponse):HttpResponse = { 

    //If we get a text/plain response entity, remap it otherwise do nothing 
    val newResp = resp.entity match{ 
    case HttpEntity.Strict(ContentTypes.`text/plain(UTF-8)` , content) => 
     val jsonResp = s"""{"error": "${content.utf8String}"}""" 
     resp.copy(entity = HttpEntity(ContentTypes.`application/json`, jsonResp)) 
    case other => 
     resp 
    } 

    newResp 
} 

これは非常に基本的な例であり、あなたはjsonを生成するより良い方法があると思いますが、これは単にデフォルトの拒否ハンドラからプランテキスト応答を修正する方法を示しています。ここで、mapResponseのデフォルトの拒否ハンドラを明示的にネストする必要があります。なぜなら、自動処理が定義したツリーの最上位レベルに追加されるため、mapResponseは拒否のケースを見ることができないからです。あなたはまだRejectionHandler.default経由でデフォルトの処理を取得します。

うまくいけば、これはあなたが後にしたものに近いでしょう。

+0

非常に興味深いですが、私はマップレスポンスとの組み合わせを考えなかったので、そのオプションを見ていきます。 – AlexC

+0

カスタムRejectionHandlerとして書くことはできますか?あなたのケースでは '指令 'を持っている出口で' Route'が必要なので、私はそのような解決策を出すことができませんでした。 – expert

+0

@ruslan、私はあなたが何を求めているのかよく分かりません。ここで説明するカスタム拒否ハンドラを作成することもできます。http://doc.akka.io/docs/akka-stream-and-http-experimental/2.0.2/scala/http/routing-dsl/rejections.html# Customizing_Rejection_Handling。出口で 'Route'対' Directive'をなぜ意味するのか分かりません。おそらくあなたの状況をより良く説明する、これに基づいた新しい質問を作成するでしょう。 – cmbaxter

関連する問題