Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: setting jsoniter config with application.conf #272

Merged
merged 3 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.innfactory.smithy4play

import com.github.plokhotnyuk.jsoniter_scala.core.ReaderConfig
import de.innfactory.smithy4play.middleware.MiddlewareBase
import play.api.mvc.ControllerComponents
import play.api.routing.Router.Routes
Expand All @@ -17,9 +18,9 @@ trait AutoRoutableController {
service: smithy4s.Service[Alg],
ec: ExecutionContext,
cc: ControllerComponents
): Seq[MiddlewareBase] => Routes = (middlewares: Seq[MiddlewareBase]) =>
new SmithyPlayRouter[Alg, F](impl, service).routes(middlewares)
): (Seq[MiddlewareBase], ReaderConfig) => Routes = (middlewares: Seq[MiddlewareBase], readerConfig: ReaderConfig) =>
new SmithyPlayRouter[Alg, F](impl, service).routes(middlewares, readerConfig)

val router: Seq[MiddlewareBase] => Routes
val router: (Seq[MiddlewareBase], ReaderConfig) => Routes

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.innfactory.smithy4play

import com.github.plokhotnyuk.jsoniter_scala.core.ReaderConfig
import com.typesafe.config.Config
import de.innfactory.smithy4play.middleware.{ MiddlewareBase, MiddlewareRegistryBase, ValidateAuthMiddleware }
import io.github.classgraph.{ ClassGraph, ScanResult }
Expand All @@ -22,7 +23,8 @@ class AutoRouter @Inject(
config: Config
) extends BaseRouter {

private val pkg = config.getString("smithy4play.autoRoutePackage")
private val pkg = config.getString("smithy4play.autoRoutePackage")
private val readerConfig = ReaderConfig.fromApplicationConfig(config)

override val controllers: Seq[Routes] = {
val classGraphScanner: ScanResult = new ClassGraph().enableAllInfo().acceptPackages(pkg).scan()
Expand All @@ -39,7 +41,7 @@ class AutoRouter @Inject(

private def createFromClass(clazz: Class[_], middlewares: Seq[MiddlewareBase]): Routes =
app.injector.instanceOf(clazz) match {
case c: AutoRoutableController => c.router(middlewares)
case c: AutoRoutableController => c.router(middlewares, readerConfig)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ object AutoRoutingMacro {
with ..$parentss
with de.innfactory.smithy4play.AutoRoutableController
{ $self =>
override val router: Seq[de.innfactory.smithy4play.middleware.MiddlewareBase] => play.api.routing.Router.Routes = this
override val router:
(Seq[de.innfactory.smithy4play.middleware.MiddlewareBase], com.github.plokhotnyuk.jsoniter_scala.core.ReaderConfig)
=> play.api.routing.Router.Routes = this
..$body }
"""
case _ =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.innfactory.smithy4play

import com.github.plokhotnyuk.jsoniter_scala.core.ReaderConfig
import play.api.http.MimeTypes
import smithy4s.capability.instances.either._
import smithy4s.codecs.Writer.CachedCompiler
Expand All @@ -11,12 +12,13 @@ import smithy4s.schema.CachedSchemaCompiler
import smithy4s.xml.Xml
import smithy4s.{ codecs, Blob }

object CodecDecider {
case class CodecDecider(readerConfig: ReaderConfig) {

private val jsonCodecs = Json.payloadCodecs
.withJsoniterCodecCompiler(
Json.jsoniter
)
.withJsoniterReaderConfig(readerConfig)

private val jsonEncoder: BlobEncoder.Compiler = jsonCodecs.encoders
private val jsonDecoder: BlobDecoder.Compiler = jsonCodecs.decoders
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,24 @@
package de.innfactory.smithy4play

import alloy.SimpleRestJson
import aws.protocols.RestXml
import cats.data.{ EitherT, Kleisli }
import de.innfactory.smithy4play
import de.innfactory.smithy4play.middleware.MiddlewareBase
import play.api.http.MimeTypes
import play.api.mvc._
import smithy4s.codecs.PayloadError
import smithy4s.http._
import smithy4s.kinds.FunctorInterpreter
import smithy4s.schema.Schema
import smithy4s.{ Blob, Endpoint, Service }

import javax.inject.Inject
import scala.concurrent.{ ExecutionContext, Future }

class SmithyPlayEndpoint[Alg[_[_, _, _, _, _]], F[_] <: ContextRoute[_], Op[
_,
_,
_,
_,
_
], I, E, O, SI, SO](
class SmithyPlayEndpoint[Alg[_[_, _, _, _, _]], F[_] <: ContextRoute[_], Op[_, _, _, _, _], I, E, O, SI, SO](
service: Service[Alg],
impl: FunctorInterpreter[Op, F],
middleware: Seq[MiddlewareBase],
endpoint: Endpoint[Op, I, E, O, SI, SO]
endpoint: Endpoint[Op, I, E, O, SI, SO],
codecDecider: CodecDecider
)(implicit cc: ControllerComponents, ec: ExecutionContext)
extends AbstractController(cc) {

Expand Down Expand Up @@ -71,7 +64,7 @@ class SmithyPlayEndpoint[Alg[_[_, _, _, _, _]], F[_] <: ContextRoute[_], Op[
private def mapToEndpointResult(
statusCode: Int
)(output: O)(implicit defaultContentType: ContentType): HttpResponse[Blob] =
CodecDecider
codecDecider
.httpMessageEncoder(Seq(defaultContentType.value))
.fromSchema(outputSchema)
.write(
Expand Down Expand Up @@ -106,7 +99,7 @@ class SmithyPlayEndpoint[Alg[_[_, _, _, _, _]], F[_] <: ContextRoute[_], Op[
)(implicit defaultContentType: ContentType): EitherT[Future, ContextRouteError, I] =
EitherT {
Future {
val codec = CodecDecider.requestDecoder(Seq(defaultContentType.value))
val codec = codecDecider.requestDecoder(Seq(defaultContentType.value))
codec
.fromSchema(inputSchema)
.decode({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package de.innfactory.smithy4play

import cats.implicits.toTraverseOps
import com.github.plokhotnyuk.jsoniter_scala.core.ReaderConfig
import com.typesafe.config.Config
import de.innfactory.smithy4play.middleware.MiddlewareBase
import play.api.mvc.{ AbstractController, ControllerComponents, Handler, RequestHeader }
import play.api.routing.Router.Routes
Expand All @@ -21,12 +23,13 @@ class SmithyPlayRouter[Alg[_[_, _, _, _, _]], F[
)(implicit cc: ControllerComponents, ec: ExecutionContext)
extends AbstractController(cc) {

def routes(middlewares: Seq[MiddlewareBase]): Routes = {
def routes(middlewares: Seq[MiddlewareBase], readerConfig: ReaderConfig): Routes = {

val interpreter: PolyFunction5[service.Operation, Kind1[F]#toKind5] = service.toPolyFunction[Kind1[F]#toKind5](impl)
val endpoints: Seq[service.Endpoint[_, _, _, _, _]] = service.endpoints
val httpEndpoints: Seq[Either[HttpEndpoint.HttpEndpointError, HttpEndpoint[_]]] =
endpoints.map(ep => HttpEndpoint.cast(ep.schema))
val codecDecider = CodecDecider(readerConfig)

new PartialFunction[RequestHeader, Handler] {
override def isDefinedAt(x: RequestHeader): Boolean = {
Expand All @@ -48,7 +51,8 @@ class SmithyPlayRouter[Alg[_[_, _, _, _, _]], F[
service,
interpreter,
middlewares,
endpointAndHttpEndpoint._1
endpointAndHttpEndpoint._1,
codecDecider
).handler(v1)
} match {
case Right(value) => value
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package de.innfactory.smithy4play.client

import cats.data.Kleisli
import de.innfactory.smithy4play.{ ClientResponse, RunnableClientRequest }
import com.github.plokhotnyuk.jsoniter_scala.core.ReaderConfig
import de.innfactory.smithy4play.{ ClientResponse, CodecDecider, RunnableClientRequest }
import smithy4s.Service
import smithy4s.kinds.{ Kind1, PolyFunction5 }

Expand All @@ -10,10 +11,12 @@ import scala.concurrent.ExecutionContext
private class GenericAPIClient[Alg[_[_, _, _, _, _]]](
service: Service[Alg],
client: RequestClient,
readerConfig: ReaderConfig,
additionalSuccessCodes: List[Int] = List.empty
)(implicit ec: ExecutionContext) {

private val smithyPlayClient = new SmithyPlayClient("/", service, client, additionalSuccessCodes)
private val smithyPlayClient =
new SmithyPlayClient("/", service, client, CodecDecider(readerConfig), additionalSuccessCodes)

/* Takes a service and creates a Transformation[Op, ClientRequest] */
private def transformer(): Alg[Kind1[RunnableClientRequest]#toKind5] =
Expand Down Expand Up @@ -53,31 +56,35 @@ object GenericAPIClient {
def withClientAndHeaders(
client: RequestClient,
additionalHeaders: Option[Map[String, Seq[String]]],
additionalSuccessCodes: List[Int] = List.empty
additionalSuccessCodes: List[Int] = List.empty,
readerConfig: ReaderConfig = ReaderConfig
)(implicit ec: ExecutionContext): Alg[Kind1[ClientResponse]#toKind5] =
apply(service, additionalHeaders, additionalSuccessCodes, client)
apply(service, additionalHeaders, additionalSuccessCodes, client, readerConfig)

def withClient(
client: RequestClient,
additionalSuccessCodes: List[Int] = List.empty
additionalSuccessCodes: List[Int] = List.empty,
readerConfig: ReaderConfig = ReaderConfig
)(implicit ec: ExecutionContext): Alg[Kind1[RunnableClientRequest]#toKind5] =
apply(service, client, additionalSuccessCodes)
apply(service, client, additionalSuccessCodes, readerConfig)

}

def apply[Alg[_[_, _, _, _, _]]](
serviceI: Service[Alg],
client: RequestClient,
additionalSuccessCodes: List[Int]
additionalSuccessCodes: List[Int],
readerConfig: ReaderConfig
)(implicit ec: ExecutionContext): Alg[Kind1[RunnableClientRequest]#toKind5] =
new GenericAPIClient(serviceI, client, additionalSuccessCodes).transformer()
new GenericAPIClient(serviceI, client, readerConfig, additionalSuccessCodes).transformer()

def apply[Alg[_[_, _, _, _, _]]](
serviceI: Service[Alg],
additionalHeaders: Option[Map[String, Seq[String]]],
additionalSuccessCodes: List[Int],
client: RequestClient
client: RequestClient,
readerConfig: ReaderConfig
)(implicit ec: ExecutionContext): Alg[Kind1[ClientResponse]#toKind5] =
new GenericAPIClient(serviceI, client, additionalSuccessCodes).transformer(additionalHeaders)
new GenericAPIClient(serviceI, client, readerConfig, additionalSuccessCodes).transformer(additionalHeaders)

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package de.innfactory.smithy4play.client

import cats.implicits.toBifunctorOps
import de.innfactory.smithy4play.ClientResponse
import com.github.plokhotnyuk.jsoniter_scala.core.ReaderConfig
import de.innfactory.smithy4play.{ ClientResponse, CodecDecider }
import smithy4s.Blob
import smithy4s.http.{ CaseInsensitive, HttpEndpoint }

Expand All @@ -11,6 +12,7 @@ class SmithyPlayClient[Alg[_[_, _, _, _, _]], F[_]](
baseUri: String,
val service: smithy4s.Service[Alg],
client: RequestClient,
codecDecider: CodecDecider,
additionalSuccessCodes: List[Int] = List.empty
)(implicit executionContext: ExecutionContext) {

Expand All @@ -31,7 +33,8 @@ class SmithyPlayClient[Alg[_[_, _, _, _, _]], F[_]](
httpEndpoint = httpEndpoint,
input = service.input(op),
serviceHints = service.hints,
client = client
client = client,
codecDecider = codecDecider
).send()
)
.toOption
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ private[smithy4play] class SmithyPlayClientEndpoint[Op[_, _, _, _, _], I, E, O,
additionalSuccessCodes: List[Int],
httpEndpoint: HttpEndpoint[I],
input: I,
client: RequestClient
client: RequestClient,
codecDecider: CodecDecider
)(implicit executionContext: ExecutionContext) {

private implicit val inputSchema: Schema[I] = endpoint.input
Expand Down Expand Up @@ -53,7 +54,7 @@ private[smithy4play] class SmithyPlayClientEndpoint[Op[_, _, _, _, _], I, E, O,
}

private def writeInputToBlob(input: I, contentType: Seq[String]): EndpointRequest = {
val codecs = CodecDecider.requestEncoder(contentType)
val codecs = codecDecider.requestEncoder(contentType)
codecs.fromSchema(inputSchema).write(PlayHttpRequest(Blob.empty, Metadata.empty), input)
}

Expand All @@ -72,7 +73,7 @@ private[smithy4play] class SmithyPlayClientEndpoint[Op[_, _, _, _, _], I, E, O,
Future {
val headers = response.headers.map(x => (x._1, x._2))
val contentType = headers.getOrElse(contentTypeKey, Seq(serviceContentType))
val codec = CodecDecider.httpResponseDecoder(contentType)
val codec = codecDecider.httpResponseDecoder(contentType)

codec
.fromSchema(outputSchema)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package de.innfactory
import alloy.SimpleRestJson
import aws.protocols.RestXml
import cats.data.{ EitherT, Kleisli }
import com.github.plokhotnyuk.jsoniter_scala.core.ReaderConfig
import com.typesafe.config.Config
import de.innfactory.smithy4play.client.SmithyPlayClientEndpointErrorResponse
import org.slf4j
import play.api.Logger
Expand All @@ -15,6 +17,7 @@ import smithy4s.http.{ CaseInsensitive, HttpEndpoint, HttpResponse, Metadata }
import scala.annotation.{ compileTimeOnly, StaticAnnotation }
import scala.concurrent.Future
import scala.language.experimental.macros
import scala.util.Try
import scala.util.matching.Regex
import scala.xml.Elem

Expand Down Expand Up @@ -65,6 +68,42 @@ package object smithy4play {
}
}

implicit class EnhancedReaderConfig(readerConfig: ReaderConfig) {

def fromApplicationConfig(config: Config): ReaderConfig = {
val maxCharBufSize =
Try(config.getInt("smithy4play.jsoniter.maxCharBufSize")).toOption
val preferredBufSize =
Try(config.getInt("smithy4play.jsoniter.preferredBufSize")).toOption
val preferredCharBufSize =
Try(config.getInt("smithy4play.jsoniter.preferredCharBufSize")).toOption
val hexDumpSize =
Try(config.getInt("smithy4play.jsoniter.hexDumpSize")).toOption
val maxBufSize =
Try(config.getInt("smithy4play.jsoniter.MaxBufSize")).toOption
val throwReaderExceptionWithStackTrace =
Try(config.getBoolean("smithy4play.jsoniter.throwReaderExceptionWithStackTrace")).toOption
val appendHexDumpToParseException =
Try(config.getBoolean("smithy4play.jsoniter.appendHexDumpToParseException")).toOption
val checkForEndOfInput =
Try(config.getBoolean("smithy4play.jsoniter.checkForEndOfInput")).toOption

readerConfig
.withMaxCharBufSize(maxCharBufSize.getOrElse(readerConfig.maxCharBufSize))
.withPreferredBufSize(preferredBufSize.getOrElse(readerConfig.preferredBufSize))
.withCheckForEndOfInput(checkForEndOfInput.getOrElse(readerConfig.checkForEndOfInput))
.withPreferredCharBufSize(preferredCharBufSize.getOrElse(readerConfig.preferredCharBufSize))
.withHexDumpSize(hexDumpSize.getOrElse(readerConfig.hexDumpSize))
.withMaxBufSize(maxBufSize.getOrElse(readerConfig.maxBufSize))
.withAppendHexDumpToParseException(
appendHexDumpToParseException.getOrElse(readerConfig.appendHexDumpToParseException)
)
.withThrowReaderExceptionWithStackTrace(
throwReaderExceptionWithStackTrace.getOrElse(readerConfig.throwReaderExceptionWithStackTrace)
)
}
}

implicit class EnhancedThrowable(throwable: Throwable) {
private val regex1: Regex = """(?s), offset: (?:0x)?[0-9a-fA-F]+, buf:.*""".r
private val regex2: Regex = """(.*), offset: .*, buf:.* (\(path:.*\))""".r
Expand All @@ -77,7 +116,6 @@ package object smithy4play {
case msg => regex1.replaceAllIn(msg, "")
}
)

}

private[smithy4play] case class Smithy4PlayError(
Expand Down
8 changes: 2 additions & 6 deletions smithy4playTest/test/XmlControllerTest.scala
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import de.innfactory.smithy4play.CodecDecider
import de.innfactory.smithy4play.client.GenericAPIClient.EnhancedGenericAPIClient
import de.innfactory.smithy4play.client.SmithyPlayTestUtils._
import models.NodeImplicits.NodeEnhancer
import models.TestBase
import play.api.Application
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.json.{ JsValue, Json, OFormat }
import play.api.libs.json.{Json, OFormat}
import play.api.test.FakeRequest
import play.api.test.Helpers._
import smithy4s.Blob
import smithy4s.http.CaseInsensitive
import testDefinitions.test.{ XmlTestInputBody, XmlControllerDefGen, XmlTestOutput }
import testDefinitions.test.{XmlControllerDefGen, XmlTestInputBody, XmlTestOutput}

import scala.xml._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.xml.{ Elem, Node, PrettyPrinter }

class XmlControllerTest extends TestBase {

Expand Down
Loading