Skip to content

Instantly share code, notes, and snippets.

@jmcardon
Created March 7, 2018 19:10
Show Gist options
  • Save jmcardon/4321ba68810edefcd47cf5e1894de089 to your computer and use it in GitHub Desktop.
Save jmcardon/4321ba68810edefcd47cf5e1894de089 to your computer and use it in GitHub Desktop.
import cats.{Applicative, Monad}
import cats.syntax.all._
import org.http4s._
sealed trait Route[F[_]] {
def run(r: Request[F]): F[Response[F]]
def <+>(other: Route[F]): Route[F]
}
case class PartialRoute[F[_]](pf: PartialFunction[Request[F], F[Response[F]]])(implicit F: Monad[F])
extends Route[F] {
def <+>(other: Route[F]): Route[F] = other match {
case PartialRoute(pfother) => PartialRoute(pf.orElse(pfother))
case EffectingRoute(eff) =>
EffectingRoute[F] { r =>
if (pf.isDefinedAt(r))
pf(r).map(Some(_))
else
eff(r)
}
}
def run(r: Request[F]): F[Response[F]] =
pf.applyOrElse[Request[F], F[Response[F]]](r, _ => F.pure(Response.notFound[F]))
}
case class EffectingRoute[F[_]](eff: Request[F] => F[Option[Response[F]]])(implicit F: Monad[F])
extends Route[F] {
def run(r: Request[F]): F[Response[F]] = eff(r).flatMap(_.fold(Response.notFound[F].pure[F])(_.pure[F]))
def <+>(other: Route[F]) = other match {
case PartialRoute(pf) =>
EffectingRoute[F] { r =>
eff(r).flatMap {
case Some(res) => F.pure(Some(res))
case None =>
if (pf.isDefinedAt(r))
pf(r).map(s => Some(s))
else F.pure(None)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment