aboutsummaryrefslogblamecommitdiff
path: root/src/main/scala/xyz/driver/core/rest/Swagger.scala
blob: ab5ad76ab0b967cfff6c74e926be0a447f5992e8 (plain) (tree)
1
2
3
4
5
6
7
8
9

                            
                                      
                                                 
                                      
                                 
                                       
                               
                           
 


                                          
 

                              
                                       
                    



                                
 










































                                                                              






















                                                                         


                                              
                                              
 
 
package xyz.driver.core.rest

import akka.http.scaladsl.server.Route
import com.github.swagger.akka.SwaggerHttpService
import com.github.swagger.akka.model._
import com.typesafe.config.Config
import com.typesafe.scalalogging.Logger
import io.swagger.models.Scheme
import io.swagger.util.Json

import scala.reflect.runtime.universe
import scala.reflect.runtime.universe.Type
import scala.util.control.NonFatal

class Swagger(
    override val host: String,
    override val schemes: List[Scheme],
    version: String,
    val apiTypes: Seq[Type],
    val config: Config,
    val logger: Logger)
    extends SwaggerHttpService {

  lazy val mirror = universe.runtimeMirror(getClass.getClassLoader)

  override val apiClasses = apiTypes.map { tpe =>
    mirror.runtimeClass(tpe.typeSymbol.asClass)
  }.toSet

  // Note that the reason for overriding this is a subtle chain of causality:
  //
  // 1. Some of our endpoints require a single trailing slash and will not
  // function if it is omitted
  // 2. Swagger omits trailing slashes in its generated api doc
  // 3. To work around that, a space is added after the trailing slash in the
  // swagger Path annotations
  // 4. This space is removed manually in the code below
  //
  // TODO: Ideally we'd like to drop this custom override and fix the issue in
  // 1, by dropping the slash requirement and accepting api endpoints with and
  // without trailing slashes. This will require inspecting and potentially
  // fixing all service endpoints.
  override def generateSwaggerJson: String = {
    import io.swagger.models.{Swagger => JSwagger}

    import scala.collection.JavaConverters._
    try {
      val swagger: JSwagger = reader.read(apiClasses.asJava)

      // Removing trailing spaces
      swagger.setPaths(
        swagger.getPaths.asScala
          .map {
            case (key, path) =>
              key.trim -> path
          }
          .toMap
          .asJava)

      Json.pretty().writeValueAsString(swagger)
    } catch {
      case NonFatal(t) =>
        logger.error("Issue with creating swagger.json", t)
        throw t
    }
  }

  override val basePath: String    = config.getString("swagger.basePath")
  override val apiDocsPath: String = config.getString("swagger.docsPath")

  override val info = Info(
    config.getString("swagger.apiInfo.description"),
    version,
    config.getString("swagger.apiInfo.title"),
    config.getString("swagger.apiInfo.termsOfServiceUrl"),
    contact = Some(
      Contact(
        config.getString("swagger.apiInfo.contact.name"),
        config.getString("swagger.apiInfo.contact.url"),
        config.getString("swagger.apiInfo.contact.email")
      )),
    license = Some(
      License(
        config.getString("swagger.apiInfo.license"),
        config.getString("swagger.apiInfo.licenseUrl")
      )),
    vendorExtensions = Map.empty[String, AnyRef]
  )

  def swaggerUI: Route =
    pathEndOrSingleSlash {
      getFromResource("swagger-ui/index.html")
    } ~ getFromResourceDirectory("swagger-ui")

}