Skip to content

Commit e5f503f

Browse files
committed
Suspend run for all Http aliases
1 parent e82decf commit e5f503f

File tree

3 files changed

+42
-28
lines changed

3 files changed

+42
-28
lines changed

core/src/main/scala/org/http4s/Http.scala

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@ package org.http4s
22

33
import cats.Applicative
44
import cats.data.Kleisli
5+
import cats.effect.Sync
56

67
/** Functions for creating [[Http]] kleislis. */
78
object Http {
8-
/** Lifts a function into an [[Http]] kleisli.
9+
/** Lifts a function into an [[Http]] kleisli. The application of
10+
* `run` is suspended in `F` to permit more efficient combination
11+
* of routes via `SemigroupK`.
912
*
1013
* @tparam F the effect of the [[Response]] returned by the [[Http]]
1114
* @tparam G the effect of the bodies of the [[Request]] and [[Response]]
1215
* @param run the function to lift
13-
* @return an [[Http]] that wraps `run`
16+
* @return an [[Http]] that suspends `run`.
1417
*/
15-
def apply[F[_], G[_]](run: Request[G] => F[Response[G]]): Http[F, G] =
16-
Kleisli(run)
18+
def apply[F[_], G[_]](run: Request[G] => F[Response[G]])(implicit F: Sync[F]): Http[F, G] =
19+
Kleisli(req => F.suspend(run(req)))
1720

1821
/** Lifts an effectful [[Response]] into an [[Http]] kleisli.
1922
*
@@ -35,7 +38,9 @@ object Http {
3538
def pure[F[_]: Applicative, G[_]](r: Response[G]): Http[F, G] =
3639
Kleisli.pure(r)
3740

38-
/** Transforms an [[Http]] on its input.
41+
/** Transforms an [[Http]] on its input. The application of the
42+
* transformed function is suspended in `F` to permit more
43+
* efficient combination of routes via `SemigroupK`.
3944
*
4045
* @tparam F the effect of the [[Response]] returned by the [[Http]]
4146
* @tparam G the effect of the bodies of the [[Request]] and [[Response]]
@@ -44,6 +49,6 @@ object Http {
4449
* @return An [[Http]] whose input is transformed by `f` before
4550
* being applied to `fa`
4651
*/
47-
def local[F[_], G[_]](f: Request[G] => Request[G])(fa: Http[F, G]): Http[F, G] =
48-
Kleisli.local(f)(fa)
52+
def local[F[_], G[_]](f: Request[G] => Request[G])(fa: Http[F, G])(implicit F: Sync[F]): Http[F, G] =
53+
Kleisli(req => F.suspend(fa.run(f(req))))
4954
}

core/src/main/scala/org/http4s/HttpApp.scala

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,20 @@ package org.http4s
22

33
import cats.Applicative
44
import cats.data.Kleisli
5+
import cats.effect.Sync
56

6-
/** Functions for creating [[HttpApp]]s. */
7+
/** Functions for creating [[HttpApp]] kleislis. */
78
object HttpApp {
8-
/** Lifts a function into an [[HttpApp]].
9+
/** Lifts a function into an [[HttpApp]]. The application of `run` is
10+
* suspended in `F` to permit more efficient combination of routes
11+
* via `SemigroupK`.
912
*
1013
* @tparam F the effect of the [[HttpApp]].
1114
* @param run the function to lift
1215
* @return an [[HttpApp]] that wraps `run`
1316
*/
14-
def apply[F[_]](run: Request[F] => F[Response[F]]): HttpApp[F] =
15-
Kleisli(run)
17+
def apply[F[_]: Sync](run: Request[F] => F[Response[F]]): HttpApp[F] =
18+
Http(run)
1619

1720
/** Lifts an effectful [[Response]] into an [[HttpApp]].
1821
*
@@ -32,14 +35,16 @@ object HttpApp {
3235
def pure[F[_]: Applicative](r: Response[F]): HttpApp[F] =
3336
Kleisli.pure(r)
3437

35-
/** Transforms an [[HttpApp]] on its input.
38+
/** Transforms an [[HttpApp]] on its input. The application of the
39+
* transformed function is suspended in `F` to permit more
40+
* efficient combination of routes via `SemigroupK`.
3641
*
3742
* @tparam F the effect of the [[HttpApp]]
3843
* @param f a function to apply to the [[Request]]
3944
* @param fa the [[HttpApp]] to transform
4045
* @return An [[HttpApp]] whose input is transformed by `f` before
4146
* being applied to `fa`
4247
*/
43-
def local[F[_]](f: Request[F] => Request[F])(fa: HttpApp[F]): HttpApp[F] =
44-
Kleisli.local[F, Response[F], Request[F]](f)(fa)
48+
def local[F[_]](f: Request[F] => Request[F])(fa: HttpApp[F])(implicit F: Sync[F]): HttpApp[F] =
49+
Http.local(f)(fa)
4550
}

core/src/main/scala/org/http4s/HttpRoutes.scala

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,20 @@ import cats.data.{Kleisli, OptionT}
55
import cats.effect.Sync
66
import cats.implicits._
77

8-
/** Functions for creating [[HttpRoutes]]. */
8+
/** Functions for creating [[HttpRoutes]] kleislis. */
99
object HttpRoutes {
10-
/** Lifts a function into [[HttpRoutes]].
10+
/** Lifts a function into an [[HttpRoutes]]. The application of `run`
11+
* is suspended in `F` to permit more efficient combination of
12+
* routes via `SemigroupK`.
1113
*
1214
* @tparam F the effect of the [[HttpRoutes]]
1315
* @param run the function to lift
1416
* @return an [[HttpRoutes]] that wraps `run`
1517
*/
16-
def apply[F[_]](run: Request[F] => OptionT[F, Response[F]]): HttpRoutes[F] =
17-
Kleisli(run)
18+
def apply[F[_]: Sync](run: Request[F] => OptionT[F, Response[F]]): HttpRoutes[F] =
19+
Http(run)
1820

19-
/** Lifts an effectful [[Response]] into [[HttpRoutes]].
21+
/** Lifts an effectful [[Response]] into an [[HttpRoutes]].
2022
*
2123
* @tparam F the effect of the [[HttpRoutes]]
2224
* @param fr the effectful [[Response]] to lift
@@ -25,7 +27,7 @@ object HttpRoutes {
2527
def liftF[F[_]](fr: OptionT[F, Response[F]]): HttpRoutes[F] =
2628
Kleisli.liftF(fr)
2729

28-
/** Lifts a [[Response]] into [[HttpRoutes]].
30+
/** Lifts a [[Response]] into an [[HttpRoutes]].
2931
*
3032
* @tparam F the base effect of the [[HttpRoutes]]
3133
* @param r the [[Response]] to lift
@@ -34,28 +36,30 @@ object HttpRoutes {
3436
def pure[F[_]](r: Response[F])(implicit FO: Applicative[OptionT[F, ?]]): HttpRoutes[F] =
3537
Kleisli.pure(r)
3638

37-
/** Transforms [[HttpRoutes]] on its input.
39+
/** Transforms an [[HttpRoutes]] on its input. The application of the
40+
* transformed function is suspended in `F` to permit more
41+
* efficient combination of routes via `SemigroupK`.
3842
*
3943
* @tparam F the base effect of the [[HttpRoutes]]
4044
* @param f a function to apply to the [[Request]]
4145
* @param fa the [[HttpRoutes]] to transform
42-
* @return [[HttpRoutes]] whose input is transformed by `f` before
46+
* @return An [[HttpRoutes]] whose input is transformed by `f` before
4347
* being applied to `fa`
4448
*/
45-
def local[F[_]](f: Request[F] => Request[F])(fa: HttpRoutes[F]): HttpRoutes[F] =
46-
Kleisli.local[OptionT[F, ?], Response[F], Request[F]](f)(fa)
49+
def local[F[_]: Sync](f: Request[F] => Request[F])(fa: HttpRoutes[F]): HttpRoutes[F] =
50+
Http.local[OptionT[F, ?], F](f)(fa)
4751

4852
/** Lifts a partial function into an [[HttpRoutes]]. The application of the
49-
* partial function is delayed in `F` to permit more efficient combination
53+
* partial function is suspended in `F` to permit more efficient combination
5054
* of routes via `SemigroupK`.
5155
*
5256
* @tparam F the base effect of the [[HttpRoutes]]
53-
* @param pfthe partial function to lift
54-
* @return [[HttpRoutes]] that returns some [[Response]] in an `OptionT[F, ?]`
57+
* @param pf the partial function to lift
58+
* @return An [[HttpRoutes]] that returns some [[Response]] in an `OptionT[F, ?]`
5559
* wherever `pf` is defined, an `OptionT.none` wherever it is not
5660
*/
5761
def of[F[_]](pf: PartialFunction[Request[F], F[Response[F]]])(implicit F: Sync[F]): HttpRoutes[F] =
58-
Kleisli(req => OptionT(F.delay(pf.lift(req).sequence).flatten))
62+
Kleisli(req => OptionT(F.suspend(pf.lift(req).sequence)))
5963

6064
/** An empty set of routes. Always responds with `pOptionT.none`.
6165
*

0 commit comments

Comments
 (0)