2

ここで私自身の質問に答える.

スプレーを使用して作成している RESTful-esk サービスに取り組んでいるときに、パスの一部として英数字の ID を持つルートを照合したいと考えていました。これは私が最初に始めたものです:

case class APIPagination(val page: Option[Int], val perPage: Option[Int])
get {
  pathPrefix("v0" / "things") {
    pathEndOrSingleSlash {
      parameters('page ? 0, 'perPage ? 10).as(APIPagination) { pagination =>
        respondWithMediaType(`application/json`) {
          complete("things")
        }
      }
    } ~ 
    path(Segment) { thingStringId =>
      pathEnd {
        complete(thingStringId)
      } ~
      pathSuffix("subthings") {
        pathEndOrSingleSlash {
          complete("subthings")
        }
      } ~
      pathSuffix("othersubthings") {
        pathEndOrSingleSlash {
          complete("othersubthings")
        }
      } 
    }
  }
} ~ //more routes...

これはコンパイルに問題はありませんが、scalatest を使用してルーティング構造が正しいことを確認すると、次のような出力が得られて驚きました。

"ThingServiceTests:"
"Thing Service Routes should not reject:"
- should /v0/things
- should /v0/things/thingId
- should /v0/things/thingId/subthings *** FAILED ***
  Request was not handled (RouteTest.scala:64)
- should /v0/things/thingId/othersubthings *** FAILED ***
  Request was not handled (RouteTest.scala:64)

ルートの何が問題になっていますか?

4

1 に答える 1

5

this SO Questionthis blog postなどの多くのリソースを調べましたが、ルート構造のトップレベル部分として文字列 ID を使用することについて何も見つけられなかったようです。この重要なテストを見つける前に、 spray scaladocに目を通し、Path マッチャーに関するドキュメントに頭を悩ませました(以下に複製)

"pathPrefix(Segment)" should {
    val test = testFor(pathPrefix(Segment) { echoCaptureAndUnmatchedPath })
    "accept [/abc]" in test("abc:")
    "accept [/abc/]" in test("abc:/")
    "accept [/abc/def]" in test("abc:/def")
    "reject [/]" in test()
  }

これは私にいくつかのことを教えてくれました。pathPrefixの代わりに使ってみるべきだとpath。そこで、ルートを次のように変更しました。

get {
  pathPrefix("v0" / "things") {
    pathEndOrSingleSlash {
      parameters('page ? 0, 'perPage ? 10).as(APIPagination) { pagination =>
        respondWithMediaType(`application/json`) {
          listThings(pagination)
        }
      }
    } ~ 
    pathPrefix(Segment) { thingStringId =>
      pathEnd {
        showThing(thingStringId)
      } ~
      pathPrefix("subthings") {
        pathEndOrSingleSlash {
          listSubThingsForMasterThing(thingStringId)
        }
      } ~
      pathPrefix("othersubthings") {
        pathEndOrSingleSlash {
          listOtherSubThingsForMasterThing(thingStringId)
        }
      } 
    }
  }
} ~

そして、すべてのテストに合格し、ルート構造が適切に機能することをうれしく思います。Regex次に、代わりにマッチャーを使用するように更新します。

pathPrefix(new scala.util.matching.Regex("[a-zA-Z0-9]*")) { thingStringId =>

同様の問題に遭遇した他の人のためにSOに投稿することにしました。jrudolph がコメントで指摘しているように、これはパスの途中でSegment一致し、使用されないことが期待されているためです。<Segment><PathEnd>どちらがpathPrefixより便利ですか

于 2015-08-03T16:16:05.613 に答える