Skip to content

Commit

Permalink
Catch metadata errors in operations without an Errorable (#622)
Browse files Browse the repository at this point in the history
  • Loading branch information
kubukoz authored Nov 22, 2022
1 parent b662fc2 commit b078966
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 9 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ lazy val tests = projectMatrix
Compile / smithySpecs := Seq(
(ThisBuild / baseDirectory).value / "sampleSpecs" / "pizza.smithy",
(ThisBuild / baseDirectory).value / "sampleSpecs" / "weather.smithy",
(ThisBuild / baseDirectory).value / "sampleSpecs" / "recursiveInput.smithy"
(ThisBuild / baseDirectory).value / "sampleSpecs" / "recursiveInput.smithy",
),
moduleName := {
if (virtualAxes.value.contains(CatsEffect2Axis))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,16 +206,22 @@ private[smithy4s] class SmithyHttp4sServerEndpointImpl[F[_], Op[_, _, _, _, _],
endpoint.errorable match {
case Some(errorable) =>
val processError: E => Response[F] = compileErrorable(errorable)
(_: Throwable) match {

{
case e: HttpContractError =>
Response[F](Status.BadRequest).withEntity(e).pure[F]
case endpoint.Error((_, e)) =>
F.pure(processError(e))
case e: Throwable =>
F.raiseError(e)
}
case None =>
F.raiseError(_)

case None => {
case e: HttpContractError =>
Response[F](Status.BadRequest).withEntity(e).pure[F]
case e: Throwable =>
F.raiseError(e)
}
}
}

Expand Down
16 changes: 16 additions & 0 deletions modules/http4s/test/src/smithy4s/http4s/ProtocolBuilderSpec.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2021-2022 Disney Streaming
*
* Licensed under the Tomorrow Open Source Technology License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://disneystreaming.github.io/TOST-1.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package smithy4s.http4s

import cats.effect.IO
Expand Down
16 changes: 16 additions & 0 deletions modules/json/test/src/smithy4s/http/json/JsonCodecApiTests.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2021-2022 Disney Streaming
*
* Licensed under the Tomorrow Open Source Technology License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://disneystreaming.github.io/TOST-1.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package smithy4s.http.json

import munit.FunSuite
Expand Down
5 changes: 5 additions & 0 deletions modules/tests/src/smithy4s/tests/PizzaAdminServiceImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,9 @@ class PizzaAdminServiceImpl(ref: Compat.Ref[IO, State])
def customCode(code: Int): IO[CustomCodeOutput] =
IO.pure(CustomCodeOutput(if (code != 0) Some(code) else None))

def echo(
pathParam: String,
body: EchoBody,
queryParam: Option[String]
): IO[Unit] = IO.unit
}
38 changes: 38 additions & 0 deletions modules/tests/src/smithy4s/tests/PizzaSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,44 @@ abstract class PizzaSpec
}
}

routerTest("path param failing refinement results in a BadRequest") {
(client, uri, log) =>
client
.send[Unit](
POST(uri = uri / "echo" / "too-short").withEntity(Json.obj()),
log
)
.map(_._1)
.map(assert.eql(_, 400))
}

routerTest("query param failing refinement results in a BadRequest") {
(client, uri, log) =>
client
.send[Unit](
POST(
(uri / "echo" / "long-enough")
.withQueryParam("queryParam", "too-short")
).withEntity(Json.obj()),
log
)
.map(_._1)
.map(assert.eql(_, 400))
}

routerTest("body failing refinement results in a BadRequest") {
(client, uri, log) =>
client
.send[Unit](
POST(
uri / "echo" / "long-enough"
).withEntity(Json.obj("data" -> Json.fromString("too-short"))),
log
)
.map(_._1)
.map(assert.eql(_, 400))
}

// note: these aren't really part of the pizza suite

pureTest("Happy path: httpMatch") {
Expand Down
35 changes: 30 additions & 5 deletions sampleSpecs/pizza.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ use smithy4s.api#simpleRestJson
@simpleRestJson
service PizzaAdminService {
version: "1.0.0",
errors: [GenericServerError, GenericClientError],
operations: [AddMenuItem, GetMenu, Version, Health, HeaderEndpoint, RoundTrip, GetEnum, GetIntEnum, CustomCode]
operations: [AddMenuItem, GetMenu, Version, Health, HeaderEndpoint, RoundTrip, GetEnum, GetIntEnum, CustomCode, Echo]
}

@http(method: "POST", uri: "/restaurant/{restaurant}/menu/item", code: 201)
operation AddMenuItem {
input: AddMenuItemRequest,
errors: [PriceError],
errors: [PriceError, GenericServerError, GenericClientError],
output: AddMenuItemResult
}

Expand Down Expand Up @@ -87,7 +86,7 @@ structure PriceError {
@http(method: "GET", uri: "/restaurant/{restaurant}/menu", code: 200)
operation GetMenu {
input: GetMenuRequest,
errors: [NotFoundError, FallbackError],
errors: [NotFoundError, FallbackError, GenericClientError],
output: GetMenuResult
}

Expand Down Expand Up @@ -288,4 +287,30 @@ structure CustomCodeInput {
structure CustomCodeOutput {
@httpResponseCode
code: Integer
}
}


@http(method: "POST", uri: "/echo/{pathParam}")
operation Echo {
input := {
@required
@httpLabel
@length(min: 10)
pathParam: String,

@httpQuery("queryParam")
@length(min: 10)
queryParam: String,

@httpPayload
@required
body: EchoBody
}
// this operation must NOT have any errors
errors: []
}

structure EchoBody {
@length(min: 10)
data: String
}

0 comments on commit b078966

Please sign in to comment.