From 4358103098691993fa75e9cd2d15fd8d24e60a64 Mon Sep 17 00:00:00 2001 From: Lintterer Date: Mon, 24 Jun 2024 14:25:11 +0200 Subject: [PATCH 1/2] feat: ignoring charset in content-type for encoding and decoding --- .../innfactory/smithy4play/CodecDecider.scala | 4 +- .../app/controller/XmlController.scala | 15 ++++- smithy4playTest/test/XmlControllerTest.scala | 67 ++++++++++++++++--- .../testSpecs/XmlController.smithy | 4 ++ 4 files changed, 75 insertions(+), 15 deletions(-) diff --git a/smithy4play/src/main/scala/de/innfactory/smithy4play/CodecDecider.scala b/smithy4play/src/main/scala/de/innfactory/smithy4play/CodecDecider.scala index 3c769e65..90769486 100644 --- a/smithy4play/src/main/scala/de/innfactory/smithy4play/CodecDecider.scala +++ b/smithy4play/src/main/scala/de/innfactory/smithy4play/CodecDecider.scala @@ -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 _ => @@ -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 _ => diff --git a/smithy4playTest/app/controller/XmlController.scala b/smithy4playTest/app/controller/XmlController.scala index 964ec18e..007741f0 100644 --- a/smithy4playTest/app/controller/XmlController.scala +++ b/smithy4playTest/app/controller/XmlController.scala @@ -4,7 +4,13 @@ import cats.data.{ EitherT, Kleisli } import cats.implicits.catsSyntaxEitherId import de.innfactory.smithy4play.{ AutoRouting, ContextRoute, ContextRouteError } import play.api.mvc.ControllerComponents -import testDefinitions.test.{ XmlControllerDef, XmlTestInputBody, XmlTestOutput, XmlTestWithInputAndOutputOutput } +import testDefinitions.test.{ + XmlControllerDef, + XmlTestInputBody, + XmlTestOutput, + XmlTestWithCharsetOutput, + XmlTestWithInputAndOutputOutput +} import javax.inject.{ Inject, Singleton } import scala.concurrent.{ ExecutionContext, Future } @@ -18,16 +24,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] ) ) } + } diff --git a/smithy4playTest/test/XmlControllerTest.scala b/smithy4playTest/test/XmlControllerTest.scala index d023a5a6..215a00fc 100644 --- a/smithy4playTest/test/XmlControllerTest.scala +++ b/smithy4playTest/test/XmlControllerTest.scala @@ -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 @@ -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 = + + {concatVal1} + {squareTest} + + 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 + + {concatVal1 + concatVal2} + + {squareTest * squareTest} + .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" @@ -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")) @@ -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 diff --git a/smithy4playTest/testSpecs/XmlController.smithy b/smithy4playTest/testSpecs/XmlController.smithy index 9daa33e2..5d6397b9 100644 --- a/smithy4playTest/testSpecs/XmlController.smithy +++ b/smithy4playTest/testSpecs/XmlController.smithy @@ -15,6 +15,8 @@ service XmlControllerDef { operation XmlTestWithInputAndOutput { input: XmlTestInput output := { + @httpHeader("content-type") + contentType: String @required @httpPayload body: XmlTestOutput @@ -22,6 +24,8 @@ operation XmlTestWithInputAndOutput { } structure XmlTestInput { + @httpHeader("content-type") + contentType: String @httpLabel @required xmlTest: String From e0588066e474c51e268e4999a39bb1ca566e9fcf Mon Sep 17 00:00:00 2001 From: Lintterer Date: Mon, 24 Jun 2024 14:27:23 +0200 Subject: [PATCH 2/2] chore: scalafmt --- smithy4playTest/app/controller/XmlController.scala | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/smithy4playTest/app/controller/XmlController.scala b/smithy4playTest/app/controller/XmlController.scala index 007741f0..8940aa91 100644 --- a/smithy4playTest/app/controller/XmlController.scala +++ b/smithy4playTest/app/controller/XmlController.scala @@ -4,13 +4,7 @@ import cats.data.{ EitherT, Kleisli } import cats.implicits.catsSyntaxEitherId import de.innfactory.smithy4play.{ AutoRouting, ContextRoute, ContextRouteError } import play.api.mvc.ControllerComponents -import testDefinitions.test.{ - XmlControllerDef, - XmlTestInputBody, - XmlTestOutput, - XmlTestWithCharsetOutput, - XmlTestWithInputAndOutputOutput -} +import testDefinitions.test.{ XmlControllerDef, XmlTestInputBody, XmlTestOutput, XmlTestWithInputAndOutputOutput } import javax.inject.{ Inject, Singleton } import scala.concurrent.{ ExecutionContext, Future }