Skip to content
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

Feature: Add when operator in Http #1078

Merged
merged 8 commits into from
Feb 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ object Main extends App {
.provideCustomLayer(ServerChannelFactory.auto ++ EventLoopGroup.auto(8))
.exitCode
}

private def app(response: Response) = Http.fromHExit(HExit.succeed(response))
private val path = "/plaintext"
private def app(response: Response) = Http.fromHExit(HExit.succeed(response)).whenPathEq(path)

private def server(response: Response) =
Server.app(app(response)) ++
Expand Down
24 changes: 22 additions & 2 deletions zio-http/src/main/scala/zhttp/http/Http.scala
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,12 @@ sealed trait Http[-R, +E, -A, +B] extends (A => ZIO[R, Option[E], B]) { self =>
final def unwrap[R1 <: R, E1 >: E, C](implicit ev: B <:< ZIO[R1, E1, C]): Http[R1, E1, A, C] =
self.flatMap(Http.fromZIO(_))

/**
* Applies Http based only if the condition function evaluates to true
*/
final def when[A2 <: A](f: A2 => Boolean): Http[R, E, A2, B] =
Http.When(f, self)

/**
* Widens the type of the output
*/
Expand Down Expand Up @@ -413,6 +419,8 @@ sealed trait Http[-R, +E, -A, +B] extends (A => ZIO[R, Option[E], B]) { self =>
self.execute(a).foldExit(ee(_).execute(a), bb(_).execute(a), dd.execute(a))

case RunMiddleware(app, mid) => mid(app).execute(a)

case When(f, other) => if (f(a)) other.execute(a) else HExit.empty
}
}

Expand Down Expand Up @@ -451,6 +459,16 @@ object Http {
*/
override def updateHeaders(update: Headers => Headers): HttpApp[R, E] = http.map(_.updateHeaders(update))

/**
* Applies Http based on the path
*/
def whenPathEq(p: Path): HttpApp[R, E] = http.whenPathEq(p.toString)

/**
* Applies Http based on the path as string
*/
def whenPathEq(p: String): HttpApp[R, E] = http.when(_.unsafeEncode.uri().contentEquals(p))

private[zhttp] def compile[R1 <: R](
zExec: HttpRuntime[R1],
settings: Server.Config[R1, Throwable],
Expand Down Expand Up @@ -825,9 +843,11 @@ object Http {

private case class Attempt[A](a: () => A) extends Http[Any, Nothing, Any, A]

private case object Empty extends Http[Any, Nothing, Any, Nothing]

private final case class FromHExit[R, E, B](h: HExit[R, E, B]) extends Http[R, E, Any, B]

private final case class When[R, E, A, B](f: A => Boolean, other: Http[R, E, A, B]) extends Http[R, E, A, B]

private case object Empty extends Http[Any, Nothing, Any, Nothing]

private case object Identity extends Http[Any, Nothing, Any, Nothing]
}
14 changes: 14 additions & 0 deletions zio-http/src/main/scala/zhttp/http/Request.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package zhttp.http

import io.netty.buffer.{ByteBuf, ByteBufUtil}
import io.netty.handler.codec.http.{DefaultFullHttpRequest, HttpRequest}
import zhttp.http.headers.HeaderExtension
import zio.{Chunk, Task, UIO}

Expand All @@ -21,6 +22,7 @@ trait Request extends HeaderExtension[Request] { self =>
override def method: Method = m
override def url: URL = u
override def headers: Headers = h
override def unsafeEncode: HttpRequest = self.unsafeEncode
override def remoteAddress: Option[InetAddress] = self.remoteAddress
override def data: HttpData = self.data
}
Expand Down Expand Up @@ -83,6 +85,11 @@ trait Request extends HeaderExtension[Request] { self =>
*/
def setUrl(url: URL): Request = self.copy(url = url)

/**
* Gets the HttpRequest
*/
private[zhttp] def unsafeEncode: HttpRequest

/**
* Gets the complete url
*/
Expand All @@ -108,10 +115,16 @@ object Request {
val h = headers
val ra = remoteAddress
val d = data

new Request {
override def method: Method = m
override def url: URL = u
override def headers: Headers = h
override def unsafeEncode: HttpRequest = {
val jVersion = Version.`HTTP/1.1`.toJava
val path = url.relative.encode
new DefaultFullHttpRequest(jVersion, method.toJava, path)
}
override def remoteAddress: Option[InetAddress] = ra
override def data: HttpData = d
}
Expand All @@ -137,6 +150,7 @@ object Request {
override def method: Method = req.method
override def remoteAddress: Option[InetAddress] = req.remoteAddress
override def url: URL = req.url
override def unsafeEncode: HttpRequest = req.unsafeEncode
override def data: HttpData = req.data
}

Expand Down
2 changes: 2 additions & 0 deletions zio-http/src/main/scala/zhttp/service/Handler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ private[zhttp] final case class Handler[R](

override def headers: Headers = Headers.make(jReq.headers())

override def unsafeEncode: HttpRequest = jReq

override def remoteAddress: Option[InetAddress] = {
ctx.channel().remoteAddress() match {
case m: InetSocketAddress => Some(m.getAddress)
Expand Down
14 changes: 13 additions & 1 deletion zio-http/src/test/scala/zhttp/http/HttpSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,18 @@ object HttpSpec extends DefaultRunnableSpec with HExitAssertion {
assert(actual)(isSuccess(equalTo("bar")))
}
}
},
} +
suite("when")(
test("should execute http only when condition applies") {
val app = Http.succeed(1).when((_: Any) => true)
val actual = app.execute(0)
assert(actual)(isSuccess(equalTo(1)))
} +
test("should not execute http when condition doesn't apply") {
val app = Http.succeed(1).when((_: Any) => false)
val actual = app.execute(0)
assert(actual)(isEmpty)
},
),
) @@ timeout(10 seconds)
}