sttp.tapir.redoc.Redoc.scala Maven / Gradle / Ivy
package sttp.tapir.redoc
import sttp.model.{Header, HeaderNames, MediaType, StatusCode}
import sttp.tapir._
import sttp.tapir.server.ServerEndpoint
object Redoc {
val defaultRedocVersion = "2.0.0-rc.56"
def redocHtml(title: String, specUrl: String, redocVersion: String = defaultRedocVersion): String = s"""
|
|
|
| $title
|
|
|
|
|
|
|
|
|
|
|
|
|
|""".stripMargin
def apply[F[_]](
title: String,
spec: String,
options: RedocUIOptions
): List[ServerEndpoint[Any, F]] = {
val specName = options.specName
val htmlName = options.htmlName
val prefixInput: EndpointInput[Unit] = options.pathPrefix.map(stringToPath).foldLeft(emptyInput)(_.and(_))
val baseEndpoint = infallibleEndpoint.get.in(prefixInput)
val redirectOutput = statusCode(StatusCode.PermanentRedirect).and(header[String](HeaderNames.Location))
def contentEndpoint(fileName: String, mediaType: MediaType) =
baseEndpoint.in(fileName).out(stringBody).out(header(Header.contentType(mediaType)))
val specNameLowerCase = specName.toLowerCase
val specMediaType =
if (specNameLowerCase.endsWith(".json")) MediaType("application", "json")
else if (specNameLowerCase.endsWith(".yaml") || specNameLowerCase.endsWith(".yml")) MediaType("text", "yaml")
else MediaType("text", "plain")
val specEndpoint = contentEndpoint(specName, specMediaType).serverLogicPure[F](_ => Right(spec))
val specPrefix = if (options.useRelativePaths) "." else "/" + (options.contextPath ++ options.pathPrefix).mkString("/")
val html: String = redocHtml(title, s"$specPrefix/$specName", options.redocVersion)
val htmlEndpoint = contentEndpoint(htmlName, MediaType.TextHtml).serverLogicPure[F](_ => Right(html))
val lastSegmentInput: EndpointInput[Option[String]] = extractFromRequest(_.uri.path.lastOption)
val redirectToHtmlEndpoint =
baseEndpoint
.in(lastSegmentInput)
.out(redirectOutput)
.serverLogicPure[F] { lastSegment =>
if (options.useRelativePaths) {
val pathFromLastSegment: String = lastSegment match {
case Some(s) if s.nonEmpty => s + "/"
case _ => ""
}
Right(s"./$pathFromLastSegment$htmlName")
} else
Right(options.contextPath ++ options.pathPrefix match {
case Nil => s"/$htmlName"
case segments => s"/${segments.mkString("/")}/$htmlName"
})
}
List(specEndpoint, htmlEndpoint, redirectToHtmlEndpoint)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy