Skip to content

Commit

Permalink
Issue-1438: handle new error type and return 500
Browse files Browse the repository at this point in the history
  • Loading branch information
GaryAghedo committed Jul 24, 2024
1 parent 80c4d56 commit 69a39d4
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
10 changes: 8 additions & 2 deletions modules/core/src/smithy4s/http/HttpUnaryServerCodecs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,14 @@ object HttpUnaryServerCodecs {

def encodeOutput(o: O) = F.map(base)(outputW.write(_, o))
def encodeError(e: E) = F.map(base)(errorW.write(_, e))
def httpContractErrorEncoder(e: HttpContractError) =
F.map(base)(httpContractErrorWriters.write(_, e).withStatusCode(400))

def httpContractErrorEncoder(e: HttpContractError) = {
val statusCode = e match {
case _: UpstreamServiceError => 500
case _ => 400
}
F.map(base)(httpContractErrorWriters.write(_, e).withStatusCode(statusCode))
}
def throwableEncoders(throwable: Throwable): F[HttpResponse[Blob]] =
throwable match {
case e: HttpContractError => httpContractErrorEncoder(e)
Expand Down
2 changes: 2 additions & 0 deletions modules/tests/src/smithy4s/tests/PizzaAdminServiceImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import cats.effect._
import cats.implicits._
import smithy4s.Timestamp
import smithy4s.example._
import smithy4s.http.UpstreamServiceError

import java.util.UUID

Expand Down Expand Up @@ -51,6 +52,7 @@ class PizzaAdminServiceImpl(ref: Ref[IO, State]) extends PizzaAdminService[IO] {
): IO[AddMenuItemResult] =
for {
_ <- IO.raiseError(Boom).whenA(restaurant == "boom")
_ <- IO.raiseError(UpstreamServiceError("Upstream service failure")).whenA(restaurant == "upstreamServiceError")
_ <- IO
.raiseError(
PriceError(
Expand Down
30 changes: 30 additions & 0 deletions modules/tests/src/smithy4s/tests/PizzaSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import smithy4s.http.HttpPayloadError
import smithy4s.example.PizzaAdminService
import smithy4s.http.CaseInsensitive
import smithy4s.http.HttpContractError
import smithy4s.http.UpstreamServiceError
import weaver._
import cats.Show
import org.http4s.EntityDecoder
Expand Down Expand Up @@ -463,6 +464,33 @@ abstract class PizzaSpec
}
}

routerTest("Upstream service error returns 500") { (client, uri, log) =>
val badMenuItem = Json.obj(
"food" -> pizzaItem,
"price" -> Json.fromFloatOrNull(9.0f)
)

for {
res <- client.send[Json](
POST(badMenuItem, uri / "restaurant" / "upstreamServiceError" / "menu" / "item"),
log
)
} yield {
val (code, headers, body) = res
val expectedBody =
Json.obj(
"upstreamServiceError" -> Json.obj(
"message" -> Json.fromString("Upstream service failure")
)
)
val discriminator = headers.get("X-Error-Type").flatMap(_.headOption)

expect(code == 500) &&
expect(body == expectedBody) &&
expect(discriminator == None)
}
}

type Res = (Client[IO], Uri)
def sharedResource: Resource[IO, (Client[IO], Uri)] = for {
stateRef <- Resource.eval(
Expand All @@ -476,6 +504,8 @@ abstract class PizzaSpec
smithy4s.example.GenericClientError("Oops")
case PizzaAdminServiceImpl.Boom =>
smithy4s.example.GenericServerError("Crash")
case UpstreamServiceError(message) =>
UpstreamServiceError(message)
case t: Throwable if !t.isInstanceOf[HttpContractError] =>
// This pattern allows checking that errors specified in specs
// do not get intercepted by mapErrors/flatMapErrors methods.
Expand Down

0 comments on commit 69a39d4

Please sign in to comment.