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

ba.sake.sharaf.exceptions.ExceptionMapper.scala Maven / Gradle / Ivy

package ba.sake.sharaf.exceptions

import java.net.URI
import scala.jdk.CollectionConverters.*
import io.undertow.util.StatusCodes
import ba.sake.tupson
import ba.sake.formson
import ba.sake.querson
import ba.sake.validson
import ba.sake.sharaf.*
import ProblemDetails.ArgumentProblem

/*
Why not HTTP content negotiation?
https://wiki.whatwg.org/wiki/Why_not_conneg
 */

type ExceptionMapper = PartialFunction[Throwable, Response[?]]

object ExceptionMapper {

  /*
  Only the exceptions **caused by sharaf internals** (e.g. parsing/validating request) are exposed.
  For example, if you parser JSON in your handler, that error WILL NOT BE EXPOSED/LEAKED to the user! :)
   */

  val default: ExceptionMapper = {
    case e: NotFoundException =>
      Response.withBody(e.getMessage).withStatus(StatusCodes.NOT_FOUND)
    case se: SharafException =>
      Option(se.getCause()) match
        case Some(cause) =>
          cause match
            case e: validson.ValidsonException =>
              val fieldValidationErrors = e.errors.mkString("[", "; ", "]")
              Response.withBody(s"Validation errors: $fieldValidationErrors").withStatus(StatusCodes.BAD_REQUEST)
            case e: querson.ParsingException =>
              Response.withBody(e.getMessage()).withStatus(StatusCodes.BAD_REQUEST)
            case e: tupson.ParsingException =>
              Response.withBody(e.getMessage()).withStatus(StatusCodes.BAD_REQUEST)
            case e: tupson.TupsonException =>
              Response.withBody(e.getMessage()).withStatus(StatusCodes.BAD_REQUEST)
            case e: formson.ParsingException =>
              Response.withBody(e.getMessage()).withStatus(StatusCodes.BAD_REQUEST)
            case other =>
              other.printStackTrace()
              Response.withBody("Server error").withStatus(StatusCodes.INTERNAL_SERVER_ERROR)
        case None =>
          se.printStackTrace()
          Response.withBody("Server error").withStatus(StatusCodes.INTERNAL_SERVER_ERROR)
  }

  val json: ExceptionMapper = {
    case e: NotFoundException =>
      val problemDetails = ProblemDetails(StatusCodes.NOT_FOUND, "Not Found", e.getMessage)
      Response.withBody(problemDetails).withStatus(StatusCodes.NOT_FOUND)
    case se: SharafException =>
      Option(se.getCause()) match
        case Some(cause) =>
          cause match
            case e: validson.ValidsonException =>
              val fieldValidationErrors =
                e.errors.map(err => ArgumentProblem(err.path, err.msg, Some(err.value.toString)))
              val problemDetails =
                ProblemDetails(StatusCodes.BAD_REQUEST, "Validation errors", invalidArguments = fieldValidationErrors)
              Response.withBody(problemDetails).withStatus(StatusCodes.BAD_REQUEST)
            case e: querson.ParsingException =>
              val parsingErrors = e.errors.map(err => ArgumentProblem(err.path, err.msg, err.value.map(_.toString)))
              val problemDetails =
                ProblemDetails(StatusCodes.BAD_REQUEST, "Invalid query parameters", invalidArguments = parsingErrors)
              Response.withBody(problemDetails).withStatus(StatusCodes.BAD_REQUEST)
            case e: tupson.ParsingException =>
              val parsingErrors = e.errors.map(err => ArgumentProblem(err.path, err.msg, err.value.map(_.toString)))
              val problemDetails =
                ProblemDetails(StatusCodes.BAD_REQUEST, "JSON Parsing errors", invalidArguments = parsingErrors)
              Response.withBody(problemDetails).withStatus(StatusCodes.BAD_REQUEST)
            case e: tupson.TupsonException =>
              Response
                .withBody(ProblemDetails(StatusCodes.BAD_REQUEST, "JSON parsing error", e.getMessage))
                .withStatus(StatusCodes.BAD_REQUEST)
            case e: formson.ParsingException =>
              Response
                .withBody(ProblemDetails(StatusCodes.BAD_REQUEST, "Form parsing error", e.getMessage))
                .withStatus(StatusCodes.BAD_REQUEST)
            case other =>
              other.printStackTrace()
              Response
                .withBody(ProblemDetails(StatusCodes.INTERNAL_SERVER_ERROR, "Server error", ""))
                .withStatus(StatusCodes.INTERNAL_SERVER_ERROR)
        case None =>
          se.printStackTrace()
          Response
            .withBody(ProblemDetails(StatusCodes.INTERNAL_SERVER_ERROR, "Server error", ""))
            .withStatus(StatusCodes.INTERNAL_SERVER_ERROR)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy