Skip to content

Commit

Permalink
Implement Routes#run and Route#run (zio#2552)
Browse files Browse the repository at this point in the history
* implement routes#run and route#run

* fix version specific issue
  • Loading branch information
adamgfraser authored Dec 13, 2023
1 parent 9a9aef2 commit 328729d
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
7 changes: 7 additions & 0 deletions zio-http/src/main/scala/zio/http/Route.scala
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ sealed trait Route[-Env, +Err] { self =>
*/
def routePattern: RoutePattern[_]

/**
* Applies the route to the specified request. The route must be defined for
* the request, or else this method will fail fatally.
*/
final def run(request: Request)(implicit trace: Trace): ZIO[Env, Either[Err, Response], Response] =
Routes(self).run(request)

/**
* Returns a route that automatically translates all failures into responses,
* using best-effort heuristics to determine the appropriate HTTP status code,
Expand Down
34 changes: 34 additions & 0 deletions zio-http/src/main/scala/zio/http/Routes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,40 @@ final class Routes[-Env, +Err] private (val routes: Chunk[zio.http.Route[Env, Er
def provideEnvironment(env: ZEnvironment[Env]): Routes[Any, Err] =
new Routes(routes.map(_.provideEnvironment(env)))

def run(request: Request)(implicit trace: Trace): ZIO[Env, Either[Err, Response], Response] = {

class RouteFailure[+Err](val err: Cause[Err]) extends Throwable(null, null, true, false) {
override def getMessage: String = err.unified.headOption.fold("<unknown>")(_.message)

override def getStackTrace(): Array[StackTraceElement] =
err.unified.headOption.fold[Chunk[StackTraceElement]](Chunk.empty)(_.trace).toArray

override def getCause(): Throwable =
err.find { case Cause.Die(throwable, _) => throwable }
.orElse(err.find { case Cause.Fail(value: Throwable, _) => value })
.orNull

def fillSuppressed()(implicit unsafe: Unsafe): Unit =
if (getSuppressed().length == 0) {
err.unified.iterator.drop(1).foreach(unified => addSuppressed(unified.toThrowable))
}

override def toString =
err.prettyPrint
}
var routeFailure: RouteFailure[Err] = null

handleErrorCauseZIO { cause =>
routeFailure = new RouteFailure(cause)
ZIO.refailCause(Cause.die(routeFailure))
}
.apply(request)
.mapErrorCause {
case Cause.Die(value: RouteFailure[_], _) if value == routeFailure => routeFailure.err.map(Left(_))
case cause => cause.map(Right(_))
}
}

/**
* Returns new routes that automatically translate all failures into
* responses, using best-effort heuristics to determine the appropriate HTTP
Expand Down

0 comments on commit 328729d

Please sign in to comment.