5

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

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

ただし、私が望むのは、Akka HTTP がデフォルトで提供する応答コードと、提供されるきれいな印刷メッセージであり、考えられるすべての拒否タイプの行なしで Json コントロール ラッパー内にネストされているだけです。これは可能であるように思われますが、私はそれを完了することができませんでした。

4

1 に答える 1

5

handleRejectionsと明示的に組み合わせることで、やりたいことができると思いますmapResponse。最初に、次の単純なルート定義を検討してください。

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

一致するリクエストを受け取った場合は、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

したがって、ここでは望ましくないプレーンテキストの応答が得られます。次のように、ルーティング ツリーの最上部にいくつかのディレクティブを追加することで、この問題を普遍的に解決できます。

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

次のようにwrapToJson定義されています。

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

うまくいけば、これはあなたが求めていたものに近いものです.

于 2016-01-06T13:26:24.437 に答える