Akka routing DSL не соответствует ожидаемым маршрутам

#akka #akka-http

#akka #akka-http

Вопрос:

вот три маршрута, которые я пытаюсь сопоставить

 /games/2016/1
/games/2016
/games
  

и я пытаюсь сделать это с помощью этой структуры маршрутизации:

 pathPrefix("games") {
  logger.info("INSIDE GAMES PATH KEY ")
  path(PathEnd) {
    complete("no numbers")
  } ~ path(IntNumber / IntNumber) { case (year: Int, week: Int) =>
    logger.info("Matched week/year")
    //gets games for this year and week
    complete("two numbers")
  } ~ path(IntNumber) { year: Int =>
    logger.info("Matched year")
    complete("one number")
  }
}
  

Это работает для первых двух примеров, которые у меня есть, но не работает для последнего. Что я делаю не так и как я могу это исправить, чтобы мой маршрут совпадал /games

Я пытался переключиться PathEnd на PathNetural и т. RemainingPath Д. безрезультатно.

РЕДАКТИРОВАТЬ: тестовый пример, который я использую:

   it must "return all games for this week" in {
    Get("/games") ~>
      NflRoutes.gamesRoutes ~> check {
      val games: Seq[NflGame] = responseAs[Seq[NflGame]]
      games.size must be (14)
    }
  }
  

и ошибка с журналами:

 > test-only *NflRoutesTest*
[info] Compiling 1 Scala source to /home/chris/dev/suredbits-api/target/scala-2.11/classes...
[info] Compiling 1 Scala source to /home/chris/dev/suredbits-api/target/scala-2.11/test-classes...
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/chris/dev/suredbits-api/lib/nfldb-api-assembly-0.0.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/chris/.ivy2/cache/ch.qos.logback/logback-classic/jars/logback-classic-1.0.13.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
13:09:39.721 TKD [com-suredbits-api-routes-NflRoutesTest-akka.actor.default-dispatcher-3] INFO  akka.event.slf4j.Slf4jLogger - Slf4jLogger started
13:09:39.907 TKD [suredbits-api-akka.actor.default-dispatcher-4] INFO  akka.event.slf4j.Slf4jLogger - Slf4jLogger started
13:09:40.012 TKD [pool-9-thread-6-ScalaTest-running-NflRoutesTest] INFO  c.suredbits.api.routes.NflRoutes$ - INSIDE GAMES PATH KEY 
[info] NflRoutesTest:
[info] - must return all games for this week *** FAILED ***
[info]   Request was rejected (DynamicVariable.scala:58)
[info] ScalaTest
[info] Run completed in 934 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 0, failed 1, canceled 0, ignored 0, pending 0
[info] *** 1 TEST FAILED ***
[error] Failed: Total 1, Failed 1, Errors 0, Passed 0
[error] Failed tests:
[error]     com.suredbits.api.routes.NflRoutesTest
[error] (test:testOnly) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 4 s, completed Oct 10, 2016 1:09:40 PM
> 
  

Ответ №1:

Попробуйте pathEnd сначала сопоставить. Основываясь на документации, я добавил некоторую базовую логику вместо вашей ??? :

 val fooRoute = pathPrefix("games") {
  pathEnd { complete ("empty path") } ~
  path(IntNumber / IntNumber) {case (a : Int, b : Int) => complete(s"a = $a b = $b")} ~
  path(IntNumber) { case a : Int => complete(s"a = $a")}
}
  

Этот маршрут можно протестировать с помощью следующего кода, который передает:

 Get("/games") ~> fooRoute ~> check {
  responseAs[String] equalsIgnoreCase "empty path"
}

Get("/games/2016") ~> fooRoute ~> check {
  responseAs[String] equalsIgnoreCase "a = 2016"
}

Get("/games/2016/1") ~> fooRoute ~> check {
  responseAs[String] equalsIgnoreCase "a = 2016 b = 1"
}
  

Комментарии:

1. @ChrisStewart я добавил некоторые функциональные возможности и модульные тесты, которые проходят. Можете ли вы уточнить «не сработало»?

2. Я отредактировал OP, чтобы быть более реалистичным, обратите внимание, что "INSIDE GAMES PATH KEY " при проверке моего пути отображается сообщение журнала.

3. @ChrisStewart Измените path(PathEnd) {... директиву pathEnd {... . В документах есть примечание: пустая строка (также называемая пустым словом или идентификатором) является нейтральным элементом операции конкатенации строк, поэтому она будет соответствовать всему, но помните, что для этого пути требуется сопоставление всего оставшегося пути

4. Вы также можете создать фактическое дерево, используя pathPrefix(IntNumber) { a => pathEnd { /* your last case */ } ~ path(IntNumber) { b => /* your second case */ } }