如何在 Akka-HTTP 中将两个指令与 OR 一起使用?
How do I use two Directives with OR in Akka-HTTP?
我想在 Akka HTTP 中创建一个复杂的指令,我可以在其中使用查询 /api/guitar?id=42
或路径 /api/guitar/42
。我确实使用了两个指令并且它起作用了。但是,我想在一个指令中使用所有内容,这样我就可以从 |
运算符中受益。所以,我有这个代码:
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
object ComplexDirectives {
def main(args: Array[String]): Unit = {
implicit val system = ActorSystem("ComplexDirectives")
val complexRoute: Route = path("api" / "guitar") {
(path("" / IntNumber) | parameter('id.as[Int])) { (itemNumber: Int) =>
get {
println(s"I found the guitar $itemNumber")
complete(HttpEntity(
ContentTypes.`text/html(UTF-8)`,
s"""
|<html>
| <body>I found the guitar $itemNumber!</body>
|</html>
|""".stripMargin
))
}
}
}
println("http GET localhost:8080/api/guitar?id=43")
println("http GET localhost:8080/api/guitar/42")
Http().newServerAt("localhost", 8080).bindFlow(complexRoute)
}
}
当我使用 HTTP GET 命令 http GET localhost:8080/api/guitar?id=43
时,我得到了 ID 为 43 的吉他。但是当我使用命令 http GET localhost:8080/api/guitar/43
时,我无法得到吉他。我还将指令更改为仅 (path(IntNumber) | parameter('id.as[Int]))
但不起作用。
您的问题是您正在尝试连接路径。为此,您需要使用 pathPrefix
。尝试做:
val complexRoute: Route = pathPrefix("api" / "guitar") {
(path(IntNumber) | parameter('id.as[Int])) { (itemNumber: Int) =>
get {
println(s"I found the guitar $itemNumber")
complete(HttpEntity(
ContentTypes.`text/html(UTF-8)`,
s"""
|<html>
| <body>I found the guitar $itemNumber!</body>
|</html>
|""".stripMargin
))
}
}
}
请注意,在声明此类路径时,更多路径可能有效。例如,http://localhost:8080/api/guitar/abc?id=43
是有效的,因为它有一个前缀 api/guitar
和一个参数 id.
如果你想阻止那些路径,你需要按以下方式使用pathEnd
或pathEndOrSingleSlash
:
(path(IntNumber) | (pathEndOrSingleSlash & parameter('id.as[Int])))
这将同时支持 http://localhost:8080/api/guitar/?id=43
和 http://localhost:8080/api/guitar?id=43
或者:
(path(IntNumber) | (pathEnd & parameter('id.as[Int])))
仅支持 http://localhost:8080/api/guitar?id=43
我想在 Akka HTTP 中创建一个复杂的指令,我可以在其中使用查询 /api/guitar?id=42
或路径 /api/guitar/42
。我确实使用了两个指令并且它起作用了。但是,我想在一个指令中使用所有内容,这样我就可以从 |
运算符中受益。所以,我有这个代码:
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
object ComplexDirectives {
def main(args: Array[String]): Unit = {
implicit val system = ActorSystem("ComplexDirectives")
val complexRoute: Route = path("api" / "guitar") {
(path("" / IntNumber) | parameter('id.as[Int])) { (itemNumber: Int) =>
get {
println(s"I found the guitar $itemNumber")
complete(HttpEntity(
ContentTypes.`text/html(UTF-8)`,
s"""
|<html>
| <body>I found the guitar $itemNumber!</body>
|</html>
|""".stripMargin
))
}
}
}
println("http GET localhost:8080/api/guitar?id=43")
println("http GET localhost:8080/api/guitar/42")
Http().newServerAt("localhost", 8080).bindFlow(complexRoute)
}
}
当我使用 HTTP GET 命令 http GET localhost:8080/api/guitar?id=43
时,我得到了 ID 为 43 的吉他。但是当我使用命令 http GET localhost:8080/api/guitar/43
时,我无法得到吉他。我还将指令更改为仅 (path(IntNumber) | parameter('id.as[Int]))
但不起作用。
您的问题是您正在尝试连接路径。为此,您需要使用 pathPrefix
。尝试做:
val complexRoute: Route = pathPrefix("api" / "guitar") {
(path(IntNumber) | parameter('id.as[Int])) { (itemNumber: Int) =>
get {
println(s"I found the guitar $itemNumber")
complete(HttpEntity(
ContentTypes.`text/html(UTF-8)`,
s"""
|<html>
| <body>I found the guitar $itemNumber!</body>
|</html>
|""".stripMargin
))
}
}
}
请注意,在声明此类路径时,更多路径可能有效。例如,http://localhost:8080/api/guitar/abc?id=43
是有效的,因为它有一个前缀 api/guitar
和一个参数 id.
如果你想阻止那些路径,你需要按以下方式使用pathEnd
或pathEndOrSingleSlash
:
(path(IntNumber) | (pathEndOrSingleSlash & parameter('id.as[Int])))
这将同时支持 http://localhost:8080/api/guitar/?id=43
和 http://localhost:8080/api/guitar?id=43
或者:
(path(IntNumber) | (pathEnd & parameter('id.as[Int])))
仅支持 http://localhost:8080/api/guitar?id=43