Scala,ZIO,Tapir -如何从头文件中检索授权令牌?

polkgigr  于 2023-01-05  发布在  Scala
关注(0)|答案(2)|浏览(170)

我已经创建了tapir端点:

val getEndpoint = endpoint.get
  .securityIn(auth.bearer[String]())
  .in("players" / path[PlayerId]("playerId"))
  .in(query[PlayerRequest]("query"))
  .errorOut(someErrors)

现在,我想读取所有传递的值:bearer tokenplayerIdquery。因此,我创建了ZIO服务器逻辑:

PlayersEndpoint.getEndpoint.zServerLogic { case (playerId, query) => 
  //some logic to do...
}

它工作正常,但没有bearer token。在这里我无法读取bearer token。我试图将其更改为以下内容:

PlayersEndpoint.getEndpoint.zServerSecurityLogic{ case (token) => 
      //do smth with token 
     }.zServerLogic { case (playerId, query) => 
          //some logic to do...
        }

但它没有工作。我想读取所有3个值,并决定在检查令牌后做什么。文档和示例非常差,没有显示如何从tapir读取令牌。你知道我应该如何正确地做吗?

pod7payv

pod7payv1#

你可以试试这个:

import org.http4s.blaze.server.BlazeServerBuilder
import org.http4s.server.Router
import sttp.tapir.server.http4s.ztapir.ZHttp4sServerInterpreter
import sttp.tapir.ztapir._
import zio._
import zio.interop.catz._
import cats.implicits._

object TapirExample extends ZIOAppDefault {
  type Env = Any

  // fake type
  type PlayerId = Int
  type PlayerRequest = Long

  def authLogic(token: String): ZIO[Any, String, String] = {
    if (token != "secret") ZIO.fail("user not login")
    else ZIO.succeed(token)
  }

  val authEndpoint: ZPartialServerEndpoint[Any, String, String, Unit, String, Unit, Any] =
    endpoint
      .securityIn(auth.bearer[String]())
      .errorOut(stringBody)
      .zServerSecurityLogic(authLogic)

  val getEndpoint =
    authEndpoint
      .get
      .in("players" / path[PlayerId]("playerId"))
      .in(query[PlayerRequest]("query"))
      .out(stringBody)
      .serverLogic(token => queryTuple => getLogic(token, queryTuple._1, queryTuple._2))

  val getRoute =
    ZHttp4sServerInterpreter()
      .from(
        List(
          getEndpoint.widen[Env]
        )
      ).toRoutes

  def getLogic(token: String, playerId: PlayerId, request: PlayerRequest): ZIO[Any, Nothing, String] = {
    ZIO.succeed(
      s"""
        | token: $token
        | id: $playerId
        | request: $request
        |""".stripMargin)
  }

  override def run: ZIO[Any with ZIOAppArgs with Scope, Any, Any] = {

    val io = ZIO.runtime[Env].flatMap { _ =>
      for {
        _ <- ZIO.executor.flatMap(executor =>
          BlazeServerBuilder[ZIO[Env, Throwable, *]]
            .withExecutionContext(executor.asExecutionContext)
            .bindHttp(9090, "0.0.0.0")
            .withHttpApp(
              Router(
                "/" -> (
                  getRoute
                )
              ).orNotFound
            )
            .serve
            .compile
            .drain)
      } yield ()
    }

    io

  }
}

库的版本是

ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := "2.13.8"

lazy val root = (project in file("."))
  .settings(
    name := "playground"
  )

val tapirVersion = "1.2.4"

val allDependency = Seq(
  "com.softwaremill.sttp.tapir" %% "tapir-http4s-server-zio" % tapirVersion,
  "org.http4s" %% "http4s-blaze-server"      % "0.23.13",
)

libraryDependencies ++= allDependency

addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.13.2" cross CrossVersion.full)

curl 试验

$ curl --location --request GET 'localhost:9090/players/233?query=334' \
--header 'Authorization: Bearer wrongtoken'
user not login

$ curl --location --request GET 'localhost:9090/players/233?query=334' \
--header 'Authorization: Bearer secret'

 token: secret
 id: 233
 request: 334

参考:

  • https://tapir.softwaremill.com/en/latest/server/logic.html#re-usable-security-logic
  • https://github.com/softwaremill/tapir/blob/5332cf64d2ae912146e281e759b750d21bd1db55/examples/src/main/scala/sttp/tapir/examples/ZioPartialServerLogicHttp4s.scala#L22-L39
41zrol4v

41zrol4v2#

我没有IDE给予你确切的代码,但是这个想法是你的zServerSecurityLogic的返回可以在下面的zServerLogic中使用。
通常,您将在zServerSecurityLogic中验证令牌,并返回某种User值,您可以将其用作zServerLogic中的输入。
但是,您也可以在安全逻辑中“什么也不做”,只传递令牌,以便它在主逻辑中可用。

相关问题