scala - 使 Rho swagger.json 不需要 Auth
问题描述
在尝试使用 Rho lib ( https://github.com/http4s/rho ) 实现自记录 API 时遇到问题 根据要求,我们的路由应受 Auth 中间件 ( https://http4s.org/v0.21/ ) 保护auth/ ),现在 Rho 中间件生成的 swagger.json 也需要身份验证。这是代码:
def startApp(xa:Transactor[IO],appConfig: AppConfig): IO[ExitCode] = {
val stream = for {
authService <- Stream.eval(IO(new AuthService(appConfig)))
routes <- Stream.eval(IO(appRoutes(xa,appConfig,authService.middleware())))
...
} yield exitCode
...
}
def appRoutes(transactor: Transactor[IO],appConfig: AppConfig,authMiddleware: AuthMiddleware[IO,APIUser]): Kleisli[IO, Request[IO], Response[IO]] = {
val service = Router[IO](
baseDataPath -> authMiddleware.apply(
AuthService.Auth.toService(BootstrapAPI.supportedAPI(transactor, appConfig).toRoutes(swaggerRhoMiddleware))))
}
有什么方法可以将 swagger.json REST 调用排除在身份验证保护之外?
解决方案
我覆盖 SwaggerSupport 并提取 swagger 路线。
import cats.effect.Sync
import cats.implicits.catsSyntaxOptionId
import org.http4s.rho.RhoMiddleware
import org.http4s.rho.RhoRoute
import org.http4s.rho.bits.PathAST.PathMatch
import org.http4s.rho.bits.PathAST.TypedPath
import org.http4s.rho.swagger.DefaultSwaggerFormats
import org.http4s.rho.swagger.SwaggerSupport
import org.http4s.rho.swagger.models._
import shapeless._
import scala.collection.immutable.Seq
import scala.reflect.runtime.universe._
object CustomSwaggerSupport {
def apply[F[_]: Sync](implicit etag: WeakTypeTag[F[_]]): CustomSwaggerSupport[F] = new CustomSwaggerSupport[F] {}
}
abstract class CustomSwaggerSupport[F[_]](implicit F: Sync[F], etag: WeakTypeTag[F[_]]) extends SwaggerSupport[F] {
/**
* Create a RhoMiddleware adding a route to get the Swagger json file
* representing the full API
*/
def createRhoMiddlewares: (RhoMiddleware[F], RhoMiddleware[F]) =
({ routes => routes }, { routes =>
lazy val swaggerSpec: Swagger =
createSwagger(
swaggerFormats = DefaultSwaggerFormats,
apiInfo = Info(
title = "API",
version = "1.0.0"
),
host = None,
basePath = "/".some,
schemes = List(Scheme.HTTP),
consumes = Nil,
produces = Nil,
security = List(SecurityRequirement("bearer", List())),
securityDefinitions = Map(
"bearer" -> ApiKeyAuthDefinition("Authorization", In.HEADER)
),
tags = Nil,
vendorExtensions = Map.empty
)(
routes
)
lazy val swaggerRoute: Seq[RhoRoute[F, _ <: HList]] =
createSwaggerRoute(swaggerSpec, TypedPath(PathMatch("swagger.json"))).getRoutes
swaggerRoute
})
}
然后我像这样使用它:
// Create a middleware that will transform RhoService into HttpService with attached Swagger definition
val (swaggerMiddleware, swaggerRoutes): (RhoMiddleware[IO], RhoMiddleware[IO]) = CustomSwaggerSupport
.apply[IO]
.createRhoMiddlewares
lazy val protectedRoutes: HttpRoutes[IO] =
routes.toRoutes(swaggerRoutes) <+> authMiddleware
.apply(Auth.toService(routes.toRoutes(swaggerMiddleware)))
推荐阅读
- java - Hadoop MapReduce 错误不同的数据类型
- jenkins - 当单元测试用例失败时,Jenkins 构建失败
- sql-server - 在 SQL Server 中编写“like 运算符”的更好方法
- html - 不安装语言包如何显示汉字?
- react-native - 如何在 React Native 中使用配置变量
- jsp - selectonemenu 中的 AJAX 不会在每次更新时调用目标
- amazon-web-services - 自动提取 S3 中的 .gz 文件
- python - 在树莓派中使用中断检查继电器的状态
- python - Python:检查数字中的条件以在列表中以 130* 开头
- javascript - 在 Angular 6 中使用地理编码 API