【问题标题】:How do I use two Directives with OR in Akka-HTTP?如何在 Akka-HTTP 中使用带有 OR 的两个指令?
【发布时间】:2020-12-22 16:29:49
【问题描述】:

我想在 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])),但不起作用。

【问题讨论】:

    标签: scala akka akka-http


    【解决方案1】:

    您的问题是您正在尝试连接路径。为此,您需要使用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。

    如果你想阻止这些路径,你需要使用pathEndpathEndOrSingleSlash,方式如下:

    (path(IntNumber) | (pathEndOrSingleSlash & parameter('id.as[Int])))
    

    这将同时支持http://localhost:8080/api/guitar/?id=43http://localhost:8080/api/guitar?id=43

    或者:

    (path(IntNumber) | (pathEnd & parameter('id.as[Int])))
    

    仅支持http://localhost:8080/api/guitar?id=43

    【讨论】:

    • 嗯,我不知道pathPrefix 存在。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-27
    • 2021-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多