All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.improving.grpc_rest_gateway.runtime.handlers.SwaggerHandler.scala Maven / Gradle / Ivy

The newest version!
package com.improving
package grpc_rest_gateway
package runtime
package handlers

import runtime.core.*
import org.apache.commons.io.IOUtils
import akka.http.scaladsl.model.{ContentType, ContentTypes, HttpEntity, HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.Directives.*

import java.nio.file.{Path, Paths}
import javax.activation.MimetypesFileTypeMap

class SwaggerHandler(handlers: Seq[GrpcGatewayHandler]) {
  import SwaggerHandler.*

  private val mimeTypes = new MimetypesFileTypeMap()
  mimeTypes.addMimeTypes("image/png png PNG")
  mimeTypes.addMimeTypes("text/css css CSS")
  private val indexPage = readSwaggerIndexPage(handlers.map(_.specificationName).distinct.sorted)

  private[runtime] val route: Route =
    pathSingleSlash {
      redirect(DocsLandingPage, StatusCodes.PermanentRedirect)
    } ~ path(DocsPrefix) {
      redirect(DocsLandingPage, StatusCodes.PermanentRedirect)
    } ~ path(DocsPrefix / IndexPage) {
      complete(
        HttpResponse(
          status = StatusCodes.OK,
          entity = HttpEntity(contentType = ContentTypes.`text/html(UTF-8)`, bytes = indexPage.getBytes)
        )
      )
    } ~ path(DocsPrefix / RemainingPath) { rem =>
      val p = Paths.get(s"/$DocsPrefix", rem.toString())
      val resourcePath = SwaggerUiPath.resolve(RootPath.relativize(p).subpath(1, p.getNameCount))
      complete(createResourceResponse(resourcePath))
    } ~ path(SpecsPrefix / RemainingPath) { rem =>
      val resourcePath = RootPath.relativize(Paths.get(s"/$SpecsPrefix", rem.toString()))
      complete(createResourceResponse(resourcePath))
    }

  private def createResourceResponse(path: Path) = {
    val unixPath = separatorsToUnix(path.toString)
    val resource = Option(Thread.currentThread().getContextClassLoader.getResourceAsStream(unixPath))
    resource match {
      case Some(is) =>
        val contentType =
          ContentType.parse(mimeTypes.getContentType(unixPath)) match {
            case Left(value) =>
              println(s"CT: $value")
              ContentTypes.`application/octet-stream`
            case Right(contentType) => contentType
          }
        HttpResponse(
          status = StatusCodes.OK,
          entity = HttpEntity(contentType = contentType, bytes = IOUtils.toByteArray(is))
        )
      case None => HttpResponse(status = StatusCodes.NotFound)
    }
  }

  private def separatorsToUnix(path: String) = path.replace('\\', '/')
}

object SwaggerHandler {
  private val SpecsPrefix = "specs"
  private val DocsPrefix = "docs"
  private val IndexPage = "index.html"
  private val DocsLandingPage = s"/$DocsPrefix/$IndexPage"
  private val RootPath = Paths.get("/")

  def apply(handlers: Seq[GrpcGatewayHandler]): SwaggerHandler = new SwaggerHandler(handlers)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy