Skip to content

Commit

Permalink
Merge pull request #569 from disneystreaming/maxArity
Browse files Browse the repository at this point in the history
allow passing in the MaxArity for the JsonSchemaVisitor
  • Loading branch information
Baccata committed Nov 16, 2022
2 parents 40d08bb + f58aacf commit d298d17
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ The `SimpleRestJson` protocol supports 3 different union encodings :

See the section about [unions](../../04-codegen/02-unions.md) for a detailed description.

## Json Array Arity
* By default there is a limit on the arity of an array, which is 1024. This is to prevent the server from being overloaded with a large array as this is a vector for attacks.
* This limit can be changed by setting the maxArity `smithy4s.http4s.SimpleRestJsonBuilder.withMaxArity(.)` to the desired value.
* an example can be seen in the [client example](03-client.md)
## Supported traits

Here is the list of traits supported by `SimpleRestJson`
Expand Down
23 changes: 10 additions & 13 deletions modules/docs/markdown/03-protocols/02-simple-rest-json/03-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ title: SimpleRestJson client

The `smithy4s-http4s` module provides functions that transform low-level http4s clients into high-level stubs, provided the corresponding service definitions (in smithy) are annotated with the `alloy#simpleRestJson` protocol.
- Uri is optional as it will default to http://localhost:8080
- the max arity of json array decoder is 1024 by default, but can be changed by calling withMaxArity on the RestJsonBuilder object

In `build.sbt`

```scala
Expand All @@ -27,19 +29,14 @@ import cats.effect.Resource
import smithy4s.hello._

object Clients {
def helloWorldClient(http4sClient: Client[IO]) : Resource[IO, HelloWorldService[IO]] =
HelloWorldService.simpleRestJson
.client(http4sClient)
.uri(Uri.unsafeFromString("http://localhost"))
.resource

// alternatively ...
def helloWorldClient2(http4sClient: Client[IO]) : Resource[IO, HelloWorldService[IO]] =
SimpleRestJsonBuilder(HelloWorldService)
.client(http4sClient)
SimpleRestJsonBuilder
.withMaxArity(2048) // prepare maximum array/object size accepted during json decoding
.apply(HelloWorldService)
.client(http4sClient)
.uri(Uri.unsafeFromString("http://localhost"))
.resource

}
```

Expand Down Expand Up @@ -101,7 +98,7 @@ structure CatchAllServerError {
And here are some scenarios using this example model. For all of these, assume that NO `X-Error-Type` header is provided.

| Status Code | Error Selected |
|-------------|-------------------------|
| ----------- | ----------------------- |
| 404 | NotFoundError |
| 400 | CatchAllClientError |
| 503 | ServiceUnavailableError |
Expand All @@ -119,7 +116,7 @@ structure AnotherError {
Would result in the following:

| Status Code | Error Selected |
|-------------|--------------------------|
| ----------- | ------------------------ |
| 404 | NotFoundError |
| 400 | **UnknownErrorResponse** |
| 503 | ServiceUnavailableError |
Expand All @@ -140,7 +137,7 @@ structure AnotherNotFoundError {
Will result in the following:

| Status Code | Error Selected |
|-------------|--------------------------|
| ----------- | ------------------------ |
| 404 | **UnknownErrorResponse** |
| 400 | UnknownErrorResponse |
| 503 | ServiceUnavailableError |
Expand Down
12 changes: 9 additions & 3 deletions modules/http4s/src/smithy4s/http4s/SimpleRestJsonBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@ package http4s

import smithy4s.internals.InputOutput

object SimpleRestJsonBuilder
object SimpleRestJsonBuilder extends SimpleRestJsonBuilder(1024)

class SimpleRestJsonBuilder(maxArity: Int)
extends SimpleProtocolBuilder[alloy.SimpleRestJson](
smithy4s.http.json.codecs(
alloy.SimpleRestJson.protocol.hintMask ++ HintMask(
InputOutput,
IntEnum
)
),
maxArity
)
)
) {
def withMaxArity(maxArity: Int): SimpleRestJsonBuilder =
new SimpleRestJsonBuilder(maxArity)
}
4 changes: 3 additions & 1 deletion modules/http4s/src/smithy4s/http4s/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ package object http4s extends Compat.Package {
implicit final class ServiceOps[Alg[_[_, _, _, _, _]]](
private[this] val serviceProvider: smithy4s.Service.Provider[Alg]
) {

@deprecated(
"this extension method is deprecated ,Use smithy4s.http4s.SimpleRestJsonBuilder"
)
def simpleRestJson: SimpleRestJsonBuilder.ServiceBuilder[Alg] =
SimpleRestJsonBuilder(serviceProvider)

Expand Down
16 changes: 11 additions & 5 deletions modules/json/src/smithy4s/http/json/codecs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ import smithy4s.schema.SchemaVisitor
import smithy4s.schema.CompilationCache

final case class codecs(
hintMask: HintMask = codecs.defaultHintMask
) extends JsonCodecAPI(codecs.schemaVisitorJCodec(_), Some(hintMask))
hintMask: HintMask = codecs.defaultHintMask,
maxArity: Int = codecs.defaultMaxArity
) extends JsonCodecAPI(codecs.schemaVisitorJCodec(_, maxArity), Some(hintMask))

object codecs {

Expand All @@ -43,13 +44,18 @@ object codecs {
// TODO: add tests for `codecs` understanding int enums. Maybe pizza spec
IntEnum
)
val defaultMaxArity: Int = 1024

private[smithy4s] def schemaVisitorJCodec(
cache: CompilationCache[JCodec]
cache: CompilationCache[JCodec],
maxArity: Int = defaultMaxArity
): SchemaVisitor[JCodec] =
new SchemaVisitorJCodec(maxArity = 1024, cache)
new SchemaVisitorJCodec(maxArity, cache)

private[smithy4s] val schemaVisitorJCodec: SchemaVisitor[JCodec] =
new SchemaVisitorJCodec(maxArity = 1024, CompilationCache.nop[JCodec])
new SchemaVisitorJCodec(
maxArity = defaultMaxArity,
CompilationCache.nop[JCodec]
)

}

0 comments on commit d298d17

Please sign in to comment.