-
Notifications
You must be signed in to change notification settings - Fork 786
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generalize AuthedRequest to ContextRequest
A ContextRequest is defined as a request with some data. AuthedRequest can be defined as a ContextRequest with auth data as the context. AuthedRequest signals that it should only be used for auth stuff, but ContextRequest opens up possibility to reuse it to other things.
- Loading branch information
Showing
6 changed files
with
89 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,13 @@ | ||
package org.http4s | ||
|
||
import cats.{Functor, ~>} | ||
import cats.Functor | ||
import cats.data.Kleisli | ||
import cats.implicits._ | ||
|
||
final case class AuthedRequest[F[_], A](authInfo: A, req: Request[F]) { | ||
def mapK[G[_]](fk: F ~> G): AuthedRequest[G, A] = | ||
AuthedRequest(authInfo, req.mapK(fk)) | ||
} | ||
|
||
object AuthedRequest { | ||
def apply[F[_]: Functor, T]( | ||
getUser: Request[F] => F[T]): Kleisli[F, Request[F], AuthedRequest[F, T]] = | ||
Kleisli(request => getUser(request).map(user => AuthedRequest(user, request))) | ||
ContextRequest[F, T](getUser) | ||
|
||
def apply[F[_], T](context: T, req: Request[F]): AuthedRequest[F, T] = | ||
ContextRequest[F, T](context, req) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package org.http4s | ||
|
||
import cats.syntax.functor._ | ||
import cats.{Functor, ~>} | ||
import cats.data.Kleisli | ||
|
||
final case class ContextRequest[F[_], A](context: A, req: Request[F]) { | ||
def mapK[G[_]](fk: F ~> G): ContextRequest[G, A] = | ||
ContextRequest(authInfo, req.mapK(fk)) | ||
|
||
def authInfo: A = context | ||
|
||
} | ||
|
||
object ContextRequest { | ||
def apply[F[_]: Functor, T]( | ||
getContext: Request[F] => F[T]): Kleisli[F, Request[F], ContextRequest[F, T]] = | ||
Kleisli(request => getContext(request).map(ctx => ContextRequest(ctx, request))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package org.http4s | ||
|
||
import cats.data.{Kleisli, OptionT} | ||
import cats.Applicative | ||
import cats.effect.Sync | ||
|
||
object ContextRoutes { | ||
|
||
/** Lifts a function into an [[ContextRoutes]]. The application of `run` | ||
* is suspended in `F` to permit more efficient combination of | ||
* routes via `SemigroupK`. | ||
* | ||
* @tparam F the effect of the [[ContextRoutes]] | ||
* @tparam T the type of the auth info in the [[ContextRequest]] accepted by the [[ContextRoutes]] | ||
* @param run the function to lift | ||
* @return an [[ContextRoutes]] that wraps `run` | ||
*/ | ||
def apply[T, F[_]](run: ContextRequest[F, T] => OptionT[F, Response[F]])( | ||
implicit F: Sync[F]): ContextRoutes[T, F] = | ||
Kleisli(req => OptionT(F.suspend(run(req).value))) | ||
|
||
/** Lifts a partial function into an [[AuthedRoutes]]. The application of the | ||
* partial function is suspended in `F` to permit more efficient combination | ||
* of authed services via `SemigroupK`. | ||
* | ||
* @tparam F the base effect of the [[AuthedRoutes]] | ||
* @param pf the partial function to lift | ||
* @return An [[AuthedRoutes]] that returns some [[Response]] in an `OptionT[F, ?]` | ||
* wherever `pf` is defined, an `OptionT.none` wherever it is not | ||
*/ | ||
def of[T, F[_]](pf: PartialFunction[ContextRequest[F, T], F[Response[F]]])( | ||
implicit F: Applicative[F]): ContextRoutes[T, F] = | ||
Kleisli(req => pf.andThen(OptionT.liftF(_)).applyOrElse(req, Function.const(OptionT.none))) | ||
|
||
/** | ||
* The empty service (all requests fallthrough). | ||
* | ||
* @tparam T - ignored. | ||
* @return | ||
*/ | ||
def empty[T, F[_]: Applicative]: ContextRoutes[T, F] = | ||
Kleisli.liftF(OptionT.none) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
server/src/main/scala/org/http4s/server/ContextMiddleware.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.http4s | ||
package server | ||
|
||
import cats.Monad | ||
import cats.data.{Kleisli, OptionT} | ||
|
||
object ContextMiddleware { | ||
def apply[F[_]: Monad, T]( | ||
getContext: Kleisli[OptionT[F, ?], Request[F], T]): ContextMiddleware[F, T] = | ||
_.compose(Kleisli((r: Request[F]) => getContext(r).map(ContextRequest(_, r)))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters