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

pl.touk.nussknacker.ui.api.NuDesignerErrorToHttp.scala Maven / Gradle / Ivy

There is a newer version: 1.17.0
Show newest version
package pl.touk.nussknacker.ui.api

import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.ExceptionHandler
import com.typesafe.scalalogging.LazyLogging
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import io.circe.Encoder
import pl.touk.nussknacker.ui._

import java.util.concurrent.ExecutionException
import scala.language.implicitConversions
import scala.util.control.NonFatal

object NuDesignerErrorToHttp extends LazyLogging with FailFastCirceSupport {

  def nuDesignerErrorHandler: ExceptionHandler = {
    import akka.http.scaladsl.server.Directives._
    ExceptionHandler { case NonFatal(e) =>
      complete(errorToHttpResponse(unwrapException(e)))
    }
  }

  def unwrapException(e: Throwable): Throwable = e match {
    case ex: ExecutionException => ex.getCause
    case other                  => other
  }

  private def errorToHttpResponse(e: Throwable): HttpResponse = e match {
    case error: NuDesignerError =>
      logError(error)
      httpResponseFrom(error)
    case ex: IllegalArgumentException =>
      logger.debug(s"Illegal argument: ${ex.getMessage}", ex)
      HttpResponse(status = StatusCodes.BadRequest, entity = ex.getMessage)
    case ex: NotImplementedError =>
      logger.error(s"Not implemented: ${ex.getMessage}", ex)
      HttpResponse(status = StatusCodes.NotImplemented, entity = ex.getMessage)
    case ex =>
      logger.error(s"Unknown error: ${ex.getMessage}", ex)
      HttpResponse(status = StatusCodes.InternalServerError, entity = ex.getMessage)
  }

  def toResponseEither[T: Encoder](either: Either[NuDesignerError, T]): ToResponseMarshallable = either match {
    case Right(t)  => t
    case Left(err) => httpResponseFrom(err)
  }

  def httpResponseFrom(error: NuDesignerError): HttpResponse = {
    HttpResponse(
      status = httpStatusCodeFrom(error),
      entity = error.getMessage
    )
  }

  private def logError(error: NuDesignerError): Unit = error match {
    case error: NotFoundError =>
      logger.debug(s"Not found error: ${error.getMessage}. ${returnedHttpStatusInfo(error)}", error)
    case error: BadRequestError =>
      logger.debug(s"Bad request error: ${error.getMessage}. ${returnedHttpStatusInfo(error)}", error)
    case error: UnauthorizedError =>
      logger.debug(s"Unauthorized error: ${error.getMessage}. ${returnedHttpStatusInfo(error)}", error)
    case error: IllegalOperationError =>
      // we decided to use WARN level here because we are not sure if the Illegal Operation Error is caused by client
      // mistake or Nu malfunction (or Nu's dependency inconsistency - eg. external modification of Schema Registry)
      logger.warn(
        s"Illegal operation error: ${error.getMessage}. ${returnedHttpStatusInfo(error)} Error details: [${error.details}].",
        error
      )
    case error: OtherError =>
      logger.debug(s"Other error: ${error.getMessage}. ${returnedHttpStatusInfo(error)}", error)
    case error: FatalError =>
      logger.error(s"Fatal error: ${error.getMessage}. ${returnedHttpStatusInfo(error)}", error)
  }

  private def returnedHttpStatusInfo(error: NuDesignerError) = {
    s"Http status ${httpStatusCodeFrom(error).intValue()} will be returned."
  }

  private def httpStatusCodeFrom(error: NuDesignerError): StatusCode = error match {
    case _: NotFoundError         => StatusCodes.NotFound
    case _: FatalError            => StatusCodes.InternalServerError
    case _: BadRequestError       => StatusCodes.BadRequest
    case _: UnauthorizedError     => StatusCodes.Unauthorized
    case _: IllegalOperationError => StatusCodes.Conflict
    case _: OtherError            => StatusCodes.InternalServerError
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy