sttp.tapir.server.vertx.VertxFutureServerOptions.scala Maven / Gradle / Ivy
The newest version!
package sttp.tapir.server.vertx
import io.vertx.core.logging.{Logger, LoggerFactory}
import io.vertx.core.{Context, Vertx}
import io.vertx.ext.web.RoutingContext
import sttp.tapir.server.interceptor.log.DefaultServerLog
import sttp.tapir.server.interceptor.{CustomiseInterceptors, Interceptor}
import sttp.tapir.{Defaults, TapirFile}
import scala.concurrent.{ExecutionContext, Future}
final case class VertxFutureServerOptions(
uploadDirectory: TapirFile,
deleteFile: TapirFile => Future[Unit],
interceptors: List[Interceptor[Future]],
private val specificExecutionContext: Option[ExecutionContext]
) extends VertxServerOptions[Future] {
def executionContextOr(default: ExecutionContext): ExecutionContext =
specificExecutionContext.getOrElse(default)
private[vertx] def executionContextOrCurrentCtx(rc: RoutingContext) =
executionContextOr(new VertxExecutionContext(rc.vertx, rc.vertx.getOrCreateContext))
def prependInterceptor(i: Interceptor[Future]): VertxFutureServerOptions =
copy(interceptors = i :: interceptors)
def appendInterceptor(i: Interceptor[Future]): VertxFutureServerOptions =
copy(interceptors = interceptors :+ i)
}
object VertxFutureServerOptions {
/** Allows customising the interceptors used by the server interpreter. */
def customiseInterceptors: CustomiseInterceptors[Future, VertxFutureServerOptions] =
CustomiseInterceptors(
createOptions = (ci: CustomiseInterceptors[Future, VertxFutureServerOptions]) =>
VertxFutureServerOptions(
VertxServerOptions.uploadDirectory(),
defaultDeleteFile,
ci.interceptors,
None
)
).serverLog(defaultServerLog(LoggerFactory.getLogger("tapir-vertx")))
val defaultDeleteFile: TapirFile => Future[Unit] = file => {
import scala.concurrent.ExecutionContext.Implicits.global
Future(Defaults.deleteFile()(file))
}
val default: VertxFutureServerOptions = customiseInterceptors.options
def defaultServerLog(log: Logger): DefaultServerLog[Future] =
DefaultServerLog(
doLogWhenReceived = debugLog(log)(_, None),
doLogWhenHandled = debugLog(log),
doLogAllDecodeFailures = infoLog(log),
doLogExceptions = (msg: String, ex: Throwable) => Future.successful { log.error(msg, ex) },
noLog = Future.successful(())
)
private def debugLog(log: Logger)(msg: String, exOpt: Option[Throwable]): Future[Unit] = Future.successful {
VertxServerOptions.debugLog(log)(msg, exOpt)
}
private def infoLog(log: Logger)(msg: String, exOpt: Option[Throwable]): Future[Unit] = Future.successful {
VertxServerOptions.infoLog(log)(msg, exOpt)
}
}
class VertxExecutionContext(val vertx: Vertx, val ctx: Context) extends ExecutionContext {
override def execute(runnable: Runnable): Unit =
if (vertx.getOrCreateContext() != ctx) {
ctx.runOnContext((_: Void) => runnable.run())
} else {
runnable.run()
}
override def reportFailure(cause: Throwable): Unit =
VertxExecutionContext.Log.error("Failed executing", cause)
}
object VertxExecutionContext {
private[vertx] val Log = LoggerFactory.getLogger(classOf[VertxExecutionContext].getName)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy