New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generalize AuthedRequest to ContextRequest #2612
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
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(context, req.mapK(fk)) | ||
|
||
@deprecated("Use context instead", "0.21.0") | ||
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))) | ||
} |
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, Defer} | ||
import cats.implicits._ | ||
|
||
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: Defer[F]): ContextRoutes[T, F] = | ||
Kleisli(req => OptionT(F.defer(run(req).value))) | ||
|
||
/** Lifts a partial function into an [[ContextRoutes]]. 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 [[ContextRoutes]] | ||
* @param pf the partial function to lift | ||
* @return An [[ContextRoutes]] 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: Defer[F], FA: Applicative[F]): ContextRoutes[T, F] = | ||
Kleisli(req => OptionT(F.defer(pf.lift(req).sequence))) | ||
|
||
/** | ||
* The empty service (all requests fallthrough). | ||
* | ||
* @tparam T - ignored. | ||
* @return | ||
*/ | ||
def empty[T, F[_]: Applicative]: ContextRoutes[T, F] = | ||
Kleisli.liftF(OptionT.none) | ||
|
||
} |
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)))) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,6 +71,12 @@ package object server { | |
type AuthMiddleware[F[_], T] = | ||
Middleware[OptionT[F, ?], AuthedRequest[F, T], Response[F], Request[F], Response[F]] | ||
|
||
/** | ||
* An HTTP middleware that adds a context. | ||
*/ | ||
type ContextMiddleware[F[_], T] = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does anybody actually use these middleware aliases? I've come to regard them as obfuscation more than anything. I wonder what others think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are using them on our project. I find them quite useful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We too use them. |
||
Middleware[OptionT[F, ?], ContextRequest[F, T], Response[F], Request[F], Response[F]] | ||
|
||
/** | ||
* Old name for SSLConfig | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing how many places this changed just in this repo, it would be a great candidate for a scalafix, but that's not essential to this PR.