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

endpoints4s.pekkohttp.server.MuxEndpoints.scala Maven / Gradle / Ivy

There is a newer version: 2.0.1
Show newest version
package endpoints4s
package pekkohttp.server

import org.apache.pekko.http.scaladsl.server.{Directives, Route}
import endpoints4s.algebra.MuxRequest

import scala.concurrent.Future
import scala.util.{Failure, Success}

/** Extends the [[Endpoints]] interpreter with [[algebra.MuxEndpoints]]
  * support.
  *
  * @group interpreters
  */
trait MuxEndpoints extends algebra.MuxEndpoints with EndpointsWithCustomErrors {

  class MuxEndpoint[Req <: MuxRequest, Resp, Transport](
      request: Request[Transport],
      response: Response[Transport]
  ) {

    def implementedBy(handler: MuxHandler[Req, Resp])(implicit
        decoder: Decoder[Transport, Req],
        encoder: Encoder[Resp, Transport]
    ): Route = handleAsync(req => Future.successful(handler(req)))

    def implementedByAsync(handler: MuxHandlerAsync[Req, Resp])(implicit
        decoder: Decoder[Transport, Req],
        encoder: Encoder[Resp, Transport]
    ): Route = handleAsync(req => handler(req))

    private def handleAsync(handler: Req { type Response = Resp } => Future[Resp])(implicit
        decoder: Decoder[Transport, Req],
        encoder: Encoder[Resp, Transport]
    ): Route =
      Directives.handleExceptions(endpointsExceptionHandler) {
        request.directive { request =>
          decoder.decode(request) match {
            case inv: Invalid => handleClientErrors(inv)
            case Valid(req) =>
              Directives.onComplete(
                handler(req.asInstanceOf[Req { type Response = Resp }])
              ) {
                case Success(result) => response(encoder.encode(result))
                case Failure(ex) =>
                  handleClientErrors(Invalid("Invalid request entity"))
              }
          }
        }
      }

  }

  def muxEndpoint[Req <: MuxRequest, Resp, Transport](
      request: Request[Transport],
      response: Response[Transport]
  ): MuxEndpoint[Req, Resp, Transport] =
    new MuxEndpoint[Req, Resp, Transport](request, response)

}

/** A function whose return type depends on the type
  * of the given `req`.
  *
  * @tparam Req  Request base type
  * @tparam Resp Response base type
  */
trait MuxHandlerAsync[Req <: MuxRequest, Resp] {
  def apply[R <: Resp](req: Req { type Response = R }): Future[R]
}

/** A function whose return type depends on the type
  * of the given `req`.
  *
  * @tparam Req  Request base type
  * @tparam Resp Response base type
  */
trait MuxHandler[Req <: MuxRequest, Resp] {
  def apply[R <: Resp](req: Req { type Response = R }): R
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy