Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
DevNico committed Jul 24, 2024
1 parent 23c9f2b commit 2da501d
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 29 deletions.
12 changes: 6 additions & 6 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ object Dependencies {
val typesafePlay = "org.playframework" %% "play" % playVersion

val scalaVersion = "3.3.1"
val smithy4sVersion = "0.18.15"
val smithy4sVersion = "0.18.23"
val smithyCore = "com.disneystreaming.smithy4s" %% "smithy4s-core" % smithy4sVersion
val smithyJson = "com.disneystreaming.smithy4s" %% "smithy4s-json" % smithy4sVersion
val smithyXml = "com.disneystreaming.smithy4s" %% "smithy4s-xml" % smithy4sVersion
val smithy4sCompliance = "com.disneystreaming.smithy4s" %% "smithy4s-compliance-tests" % smithy4sVersion
val alloyCore = "com.disneystreaming.alloy" % "alloy-core" % "0.3.6"
val alloyOpenapi = "com.disneystreaming.alloy" %% "alloy-openapi" % "0.3.6"
val alloyCore = "com.disneystreaming.alloy" % "alloy-core" % "0.3.11"
val alloyOpenapi = "com.disneystreaming.alloy" %% "alloy-openapi" % "0.3.11"

val classgraph = "io.github.classgraph" % "classgraph" % "4.8.168"
val smithyVersion = "1.45.0"
val classgraph = "io.github.classgraph" % "classgraph" % "4.8.174"
val smithyVersion = "1.50.0"
val testTraits =
"software.amazon.smithy" % "smithy-protocol-test-traits" % smithyVersion

val scalatestPlus =
"org.scalatestplus.play" %% "scalatestplus-play" % "7.0.1" % Test
val cats = "org.typelevel" %% "cats-core" % "2.9.0"
val cats = "org.typelevel" %% "cats-core" % "2.12.0"

lazy val list = Seq(
smithyCore,
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
addSbtPlugin("com.codecommit" %% "sbt-github-packages" % "0.5.3")
addSbtPlugin("org.scalameta" %% "sbt-scalafmt" % "2.5.2")
addSbtPlugin("com.disneystreaming.smithy4s" %% "smithy4s-sbt-codegen" % "0.18.15")
addSbtPlugin("com.disneystreaming.smithy4s" %% "smithy4s-sbt-codegen" % "0.18.23")
addSbtPlugin("org.playframework" % "sbt-plugin" % "3.0.1")
addSbtPlugin("org.scoverage" %% "sbt-scoverage" % "2.0.11")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ case class CodecDecider(readerConfig: ReaderConfig) {
def encoder(
contentType: Seq[String]
): CachedSchemaCompiler[codecs.BlobEncoder] =
contentType match {
contentType.map(_.split(";").head) match {
case Seq(MimeTypes.JSON) => jsonEncoder
case Seq(MimeTypes.XML) => Xml.encoders
case _ =>
Expand Down Expand Up @@ -129,7 +129,7 @@ case class CodecDecider(readerConfig: ReaderConfig) {
def decoder(
contentType: Seq[String]
): CachedSchemaCompiler[BlobDecoder] =
contentType match {
contentType.map(_.split(";").head) match {
case Seq(MimeTypes.JSON) => jsonDecoder
case Seq(MimeTypes.XML) => Xml.decoders
case _ =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ class SmithyPlayEndpoint[Alg[_[_, _, _, _, _]], F[_] <: ContextRoute[?], Op[_, _
private val endpointHints = endpoint.hints
private val serviceContentType: String = serviceHints.toMimeType

private implicit val inputSchema: Schema[I] = endpoint.input
private implicit val outputSchema: Schema[O] = endpoint.output

def handler(v1: RequestHeader): Handler =
private implicit val inputSchema: Schema[I] = endpoint.input
private implicit val outputSchema: Schema[O] = endpoint.output
private val outputMetadataEncoder: Metadata.Encoder[O] =
Metadata.Encoder.fromSchema(outputSchema)
def handler(v1: RequestHeader): Handler =
httpEndpoint.map { httpEp =>
Action.async(parse.raw) { implicit request =>
if (request.body.size > 0 && request.body.asBytes().isEmpty) {
Expand Down Expand Up @@ -64,9 +65,13 @@ class SmithyPlayEndpoint[Alg[_[_, _, _, _, _]], F[_] <: ContextRoute[?], Op[_, _

private def mapToEndpointResult(
statusCode: Int
)(output: O)(implicit defaultContentType: ContentType): HttpResponse[Blob] =
)(output: O)(implicit defaultContentType: ContentType): HttpResponse[Blob] = {
val outputContentType = outputMetadataEncoder.encode(output).headers.get(CaseInsensitive("content-type")) match {
case Some(value) => value
case None => Seq(defaultContentType.value)
}
codecDecider
.httpMessageEncoder(Seq(defaultContentType.value))
.httpMessageEncoder(outputContentType)
.fromSchema(outputSchema)
.write(
HttpResponse(
Expand All @@ -76,6 +81,7 @@ class SmithyPlayEndpoint[Alg[_[_, _, _, _, _]], F[_] <: ContextRoute[?], Op[_, _
),
output
)
}

private def getPathParams(
v1: RequestHeader,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private[smithy4play] class SmithyPlayClientEndpoint[Op[_, _, _, _, _], I, E, O,
.map(o => HttpResponse(response.statusCode, headers, o))
.leftMap {
case error: PayloadError =>
SmithyPlayClientEndpointErrorResponse(error.expected.getBytes(), response.statusCode)
SmithyPlayClientEndpointErrorResponse(error.toString().getBytes(), response.statusCode)
case error: MetadataError =>
SmithyPlayClientEndpointErrorResponse(error.getMessage().getBytes(), response.statusCode)
}
Expand Down
4 changes: 4 additions & 0 deletions smithy4playTest/app/controller/TestController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,8 @@ class TestController @Inject() (implicit
override def testWithOtherStatusCode(): ContextRoute[Unit] = Kleisli { rc =>
EitherT.rightT[Future, ContextRouteError](())
}

override def testWithJsonInputAndBlobOutput(body: JsonInput): ContextRoute[BlobResponse] = Kleisli { rc =>
EitherT.rightT[Future, ContextRouteError](BlobResponse(Blob(body.message), "image/png"))
}
}
7 changes: 5 additions & 2 deletions smithy4playTest/app/controller/XmlController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ class XmlController @Inject() (implicit

override def xmlTestWithInputAndOutput(
xmlTest: String,
body: XmlTestInputBody
body: XmlTestInputBody,
contentType: Option[String]
): ContextRoute[XmlTestWithInputAndOutputOutput] =
Kleisli { _ =>
EitherT(
Future(
XmlTestWithInputAndOutputOutput(
XmlTestOutput(body.serverzeit, body.requiredTest + xmlTest, body.requiredInt.map(i => i * i))
XmlTestOutput(body.serverzeit, body.requiredTest + xmlTest, body.requiredInt.map(i => i * i)),
contentType
)
.asRight[ContextRouteError]
)
)
}

}
11 changes: 10 additions & 1 deletion smithy4playTest/test/TestControllerTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import play.api.libs.json.{ Json, OWrites }
import play.api.mvc.Result
import play.api.test.FakeRequest
import play.api.test.Helpers._
import smithy4s.Blob
import smithy4s.{ Blob, Document }
import smithy4s.http.CaseInsensitive
import testDefinitions.test.{
JsonInput,
SimpleTestResponse,
TestControllerServiceGen,
TestRequestBody,
Expand Down Expand Up @@ -167,6 +168,14 @@ class TestControllerTest extends TestBase {
pngAsBytes mustBe result.body.body
}

"route with json body to Blob Endpoint" in {
val testString = "StringToBeParsedCorrectly"
val result = genericClient.testWithJsonInputAndBlobOutput(JsonInput(testString)).awaitRight(global, 5.hours)

result.statusCode mustBe 200
testString mustBe result.body.body.toUTF8String
}

"route to Auth Test" in {
val result = genericClient.testAuth().awaitLeft

Expand Down
67 changes: 57 additions & 10 deletions smithy4playTest/test/XmlControllerTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import models.NodeImplicits.NodeEnhancer
import models.TestBase
import play.api.Application
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.json.{Json, OFormat}
import play.api.libs.json.{ Json, OFormat }
import play.api.test.FakeRequest
import play.api.test.Helpers._
import smithy4s.http.CaseInsensitive
import testDefinitions.test.{XmlControllerDefGen, XmlTestInputBody, XmlTestOutput}
import testDefinitions.test.{ XmlControllerDefGen, XmlTestInputBody, XmlTestOutput }

import scala.concurrent.ExecutionContext.Implicits.global

Expand All @@ -33,6 +33,53 @@ class XmlControllerTest extends TestBase {
res.body.body.requiredTestStringConcat mustBe "ThisGetsConcat"
}

"route to xml with charset in header endpoint with smithy client" in {
val res = genericClient
.xmlTestWithInputAndOutput(
"Concat",
XmlTestInputBody("05.02.2024", "ThisGets", Some(10)),
Some("application/xml; charset=utf-8")
)
.awaitRight

res.body.body.requiredIntSquared mustBe Some(100)
res.body.body.requiredTestStringConcat mustBe "ThisGetsConcat"
res.headers.get(CaseInsensitive("content-type")) mustBe Some(List("application/xml; charset=utf-8"))
}

"route to xml with charset in header with external client" in {
val concatVal1 = "ConcatThis"
val concatVal2 = "Test2"
val squareTest = 3
val xml =
<XmlTestInputBody serverzeit="05.02.2024">
<requiredTest>{concatVal1}</requiredTest>
<requiredInt>{squareTest}</requiredInt>
</XmlTestInputBody>
val request = route(
app,
FakeRequest("POST", s"/xml/$concatVal2")
.withHeaders(("content-type", "application/xml; charset=utf-8"))
.withXmlBody(
xml
)
).get
status(request) mustBe 200

val result = scala.xml.XML.loadString(contentAsString(request))
val resContentType = contentType(request)
val resCharset = charset(request)


result.normalize mustBe <XmlTestOutput serverzeit="05.02.2024">
<requiredTestStringConcat>
{concatVal1 + concatVal2}</requiredTestStringConcat>
<requiredIntSquared>
{squareTest * squareTest}</requiredIntSquared>
</XmlTestOutput>.normalize
resContentType.map(_ + "; charset=" + resCharset.getOrElse("")) mustBe Some("application/xml; charset=utf-8")
}

"route to xml test endpoint with external client" in {
val concatVal1 = "ConcatThis"
val concatVal2 = "Test2"
Expand Down Expand Up @@ -115,13 +162,13 @@ class XmlControllerTest extends TestBase {
}

"route to test endpoint with external client and json protocol" in {
implicit val formatI: OFormat[XmlTestInputBody] = Json.format[XmlTestInputBody]
implicit val formatO: OFormat[XmlTestOutput] = Json.format[XmlTestOutput]
val concatVal2 = "Test2"
val concatVal1 = "ConcatThis"
val squareTest = Some(15)
val date = "05.02.2024"
val request = route(
implicit val formatI: OFormat[XmlTestInputBody] = Json.format[XmlTestInputBody]
implicit val formatO: OFormat[XmlTestOutput] = Json.format[XmlTestOutput]
val concatVal2 = "Test2"
val concatVal1 = "ConcatThis"
val squareTest = Some(15)
val date = "05.02.2024"
val request = route(
app,
FakeRequest("POST", s"/xml/$concatVal2")
.withHeaders(("content-type", "application/json"))
Expand All @@ -130,7 +177,7 @@ class XmlControllerTest extends TestBase {
)
).get
status(request) mustBe 200
val result = contentAsJson(request).as[XmlTestOutput]
val result = contentAsJson(request).as[XmlTestOutput]
result.requiredTestStringConcat mustBe concatVal1 + concatVal2
result.requiredIntSquared mustBe squareTest.map(s => s * s)
result.serverzeit mustBe date
Expand Down
18 changes: 18 additions & 0 deletions smithy4playTest/testSpecs/TestController.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ service TestControllerService {
Health
TestWithBlob
TestWithQuery
TestWithJsonInputAndBlobOutput
TestThatReturnsError
TestAuth
TestWithOtherStatusCode
Expand All @@ -27,6 +28,17 @@ service TestControllerService {
operation TestWithOtherStatusCode {
}

@auth([])
@http(method: "POST", uri: "/jsoninput/bloboutput", code: 200)
operation TestWithJsonInputAndBlobOutput {
input:= {
@httpPayload
@required
body: JsonInput
}
output: BlobResponse
}

@auth([])
@http(method: "POST", uri: "/blob", code: 200)
operation TestWithBlob {
Expand Down Expand Up @@ -134,6 +146,12 @@ structure TestResponseBody {
bodyMessage: String
}


structure JsonInput {
@required
message: String
}

@http(method: "GET", uri: "/auth", code: 200)
operation TestAuth {
}
Expand Down
4 changes: 4 additions & 0 deletions smithy4playTest/testSpecs/XmlController.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ service XmlControllerDef {
operation XmlTestWithInputAndOutput {
input: XmlTestInput
output := {
@httpHeader("content-type")
contentType: String
@required
@httpPayload
body: XmlTestOutput
}
}

structure XmlTestInput {
@httpHeader("content-type")
contentType: String
@httpLabel
@required
xmlTest: String
Expand Down

0 comments on commit 2da501d

Please sign in to comment.