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

Validate JSON body before unmarshalling into input type #203

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Leskodamus
Copy link

@Leskodamus Leskodamus commented Jul 3, 2024

Fixes #202

Instead of first reading the JSON into the input object, perform validation to return appropriate error messages in case
of trying to parse an invalid type mapping, e.g. int to string.

Originally you would get failed to decode json: json: cannot unmarshall... error and now it returns more context instead, for example:

{
  "status": "INVALID_ARGUMENT",
  "error": "invalid argument: validation failed",
  "context": {
    "body": [
      "#/name: expected string, but got number"
    ]
  }
}

@Leskodamus
Copy link
Author

Leskodamus commented Jul 4, 2024

Ugh, of course it does not perform body validation in ValidateJSONBody(jsonBody []byte) error if the schema is not found in rest.ParamInBody or the schema is nil:

func (v *Validator) ValidateJSONBody(jsonBody []byte) error {
  name := "body"
  
  schema, found := v.inNamedSchemas[rest.ParamInBody][name]
  if !found || schema == nil {
    return nil
  }
  // ...
}

It only seems to have this value if a constraint has been given to a type. In my situation it was using uint for a field that automatically set a >=0 constraint and therefore a schema was found. Changing that to int and just using a JSON tag does not make this implementation possible.

For example:

// No validation will happen.
type ExampleIn struct {
  Value int `json:"value"`
  Name string `json:"unit"`
}

// This does get validated.
type ExampleIn struct {
  Value int `json:"value" minimum:"1"`
  Name string `json:"unit"`
}

Maye we could add a way to have schema data even if it is trivial?
For example in collector.go in func (c *Collector) jsonSchemaCallback(validator rest.JSONSchemaValidator, r openapi.Reflector) openapi.JSONSchemaCallback {}:

// ...
// It'd be great to have schema data even if it is trivial.
if schema == nil || schema.IsTrivial(r.ResolveJSONSchemaRef) {
  if err := validator.AddSchema(rest.ParamIn(in), paramName, nil, required); err != nil {
    return fmt.Errorf("add validation schema %s: %w", loc, err)
}
  
  return nil
}

Then, either always validate if a schema is not nil - which does indeed affect performance if it has to go through every check although it is not necessary, or implement a separate validation for just decoding JSON bytes into a structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot validate incorrect types
1 participant