Skip to content

Commit

Permalink
Feature: Add when operator in Http (#1078)
Browse files Browse the repository at this point in the history
* perf: added when operator in http

* build fix

* removed jrequest from constructor

* fmt

* unsafeEncode: HttpRequest

* added when primitive

* refactor: rename `whenPath` to `whenPathEq`

Co-authored-by: Tushar Mathur <tusharmath@gmail.com>
  • Loading branch information
ShrutiVerma97 and tusharmath authored Feb 24, 2022
1 parent 042291a commit 9914695
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 5 deletions.
4 changes: 2 additions & 2 deletions example/src/main/scala/example/PlainTextBenchmarkServer.scala
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)
}

0 comments on commit 9914695

Please sign in to comment.