Разбор пути для ReST API в Spray

У меня есть следующий код в Spray для анализа службы REST, вызываемой пользователем:

val route = {
  pathPrefix("v0") {
    pathPrefix("pets") {
      pathEndOrSingleSlash {
        pathEnd {
          get {
            complete("/v0/pets")
          }
        } ~
        get {
          complete("/v0/pets/")
        }
      } ~
      parameters('id ?) {
        id =>
          get {
            complete("/v0/pets?id=" + id)
          }
      }
    }
  }
}

Проблема в том, что он ведет себя не так, как ожидалось. Я ожидаю следующего поведения из кода:

http://127.0.0.1/v0/pets => /v0/pets
http://127.0.0.1/v0/pets/ => /v0/pets/
http://127.0.0.1/v0/pets?id=1234 = > /v0/pets?id=Some(1234)

Но я получаю следующие результаты для запросов:

http://127.0.0.1/v0/pets => /v0/pets
http://127.0.0.1/v0/pets/ => /v0/pets
http://127.0.0.1/v0/pets?id=1234 => /v0/pets

2 ответа

Одна из проблем здесь заключается в том, что с id объявлен как optional ваш parameter Маршрут обрабатывает как наличие, так и отсутствие его (и это обрабатывает v0/pets).

Один из способов сделать это (и я также предполагаю, что вы хотите справиться только с get Запросы).

Вы в основном просто заявляете id не обязательно на вашем parameter маршрут:

val route = get {
  pathPrefix("v0") {
    pathPrefix("pets") {
      pathEnd {
        parameter('id) { id =>
          complete("/v0/pets?id=" + id)
        } ~ complete("/v0/pets")
      } ~
      pathSingleSlash {
        complete("/v0/pets/")
      }
    }
  }
}

Другой способ в основном просто использует тот факт, что id является необязательным параметром, поэтому вы просто Option:

val route = {
  pathPrefix("v0") {
    pathPrefix("pets") {
      pathEnd {
        get {
          parameters('id ?) { id =>
            id match {
              case Some(id) => complete("/v0/pets?id=" + id)
              case None => complete("/v0/pets")
            }
          }
        }
      } ~
      pathSingleSlash {
        get {
          complete("/v0/pets/")
        }
      }
    }
  }
}
pathPrefix("v0") {
  pathPrefix("pets") {
    pathEndOrSingleSlash {
      get {
      }
    }
  }
}

соответствует http://127.0.0.1/v0/pets?id=1234.

Вот почему

GET /v0/pets?id=1234
 ^   ^   ^  ^
 |___|___|__|____ get  
     |   |  |
     |   |  |
     |   |  |__ pathEndOrSlash
     |   |  
     |   |__ pathPrefix("pets")
     |
     |__ pathPrefix("v0")

Вам нужно перехватить parameter до. Пытаться

val route = {
  pathPrefix("v0") {
    pathPrefix("pets") {
      parameters('id ?) {
        id =>
          get {
            complete("/v0/pets?id=" + id)
          }
      } ~
      pathEndOrSingleSlash {
        pathEnd {
          get {
            complete("/v0/pets")
          }
        } ~
        get {
          complete("/v0/pets/")
        }
      }
    }
  }
}
Другие вопросы по тегам