![](/img/trans.png)
[英]Scala, Tapir, ZIO - add metrics interceptor with default error handler
[英]Scala, ZIO, Tapir - how to retrieve authorization token from header?
我创建了貘端点:
val getEndpoint = endpoint.get
.securityIn(auth.bearer[String]())
.in("players" / path[PlayerId]("playerId"))
.in(query[PlayerRequest]("query"))
.errorOut(someErrors)
现在,我想读取所有传递的值: bearer token
、 playerId
和query
。 所以我创建了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 个值并决定在检查令牌后做什么。 文档和示例非常糟糕,没有说明如何从貘读取令牌。 你知道我应该如何正确地做吗?
你可以试试这个:
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
参考:
我没有 IDE 可以给你确切的代码,但我的想法是你的zServerSecurityLogic
的返回可以在下面的zServerLogic
中使用。
通常您会在zServerSecurityLogic
中验证令牌并返回某种类型的User
值,您可以将其用作zServerLogic
中的输入。
但您也可以在安全逻辑中“什么都不做”,只传递令牌,以便它在主逻辑中可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.