Scala Spray中restapi的路径解析

Scala Spray中restapi的路径解析,scala,spray,spray-dsl,Scala,Spray,Spray Dsl,我在Spray中有以下代码来解析用户调用的REST服务: val route = { pathPrefix("v0") { pathPrefix("pets") { pathEndOrSingleSlash { pathEnd { get { complete("/v0/pets") } } ~ get { complete("/v0/pet

我在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
火柴

这就是为什么

GET /v0/pets?id=1234
 ^   ^   ^  ^
 |___|___|__|____ get  
     |   |  |
     |   |  |
     |   |  |__ pathEndOrSlash
     |   |  
     |   |__ pathPrefix("pets")
     |
     |__ pathPrefix("v0")
您需要先截取
参数
。试一试

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/")
        }
      }
    }
  }
}
火柴

这就是为什么

GET /v0/pets?id=1234
 ^   ^   ^  ^
 |___|___|__|____ get  
     |   |  |
     |   |  |
     |   |  |__ pathEndOrSlash
     |   |  
     |   |__ pathPrefix("pets")
     |
     |__ pathPrefix("v0")
您需要先截取
参数
。试一试

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/")
        }
      }
    }
  }
}

这里的一个问题是,由于
id
被声明为
可选
,因此您的
参数
将处理它的存在和不存在(即处理
v0/pets

一种方法(我还假设您只想处理
get
请求)

基本上,您只需在
参数上声明
id
非可选

val route = get {
  pathPrefix("v0") {
    pathPrefix("pets") {
      pathEnd {
        parameter('id) { id =>
          complete("/v0/pets?id=" + id)
        } ~ complete("/v0/pets")
      } ~
      pathSingleSlash {
        complete("/v0/pets/")
      }
    }
  }
}
另一种方法基本上就是利用
id
是可选参数这一事实,因此您只需在
选项上进行模式匹配即可:

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/")
        }
      }
    }
  }
}

这里的一个问题是,由于
id
被声明为
可选
,因此您的
参数
将处理它的存在和不存在(即处理
v0/pets

一种方法(我还假设您只想处理
get
请求)

基本上,您只需在
参数上声明
id
非可选

val route = get {
  pathPrefix("v0") {
    pathPrefix("pets") {
      pathEnd {
        parameter('id) { id =>
          complete("/v0/pets?id=" + id)
        } ~ complete("/v0/pets")
      } ~
      pathSingleSlash {
        complete("/v0/pets/")
      }
    }
  }
}
另一种方法基本上就是利用
id
是可选参数这一事实,因此您只需在
选项上进行模式匹配即可:

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/")
        }
      }
    }
  }
}

感谢@gabriele petronella的回复。但对于您建议的解决方案,最后两条路径永远不会执行。它们都只是通过第一个路径执行,并以/v0/pets/?id=none的形式打印输出。哦,是的,我的错,id的可选性使得它无论如何都要进入第一个路径。mfirry的解决方案是可行的。感谢@gabriele petronella的回复。但对于您建议的解决方案,最后两条路径永远不会执行。它们都只是通过第一个路径执行,并以/v0/pets/?id=none的形式打印输出。哦,是的,我的错,id的可选性使得它无论如何都要进入第一个路径。梅弗里的解决方案是可行的。