使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调用排除在Auth保护之外?

解决方法

我覆盖了 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)))

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...