friendsofgo / killgrave

Simple way to generate mock servers written in Go
https://friendsofgo.github.io/killgrave/
MIT License
511 stars 96 forks source link

validating a body with a schema #161

Closed amartinm7 closed 6 months ago

amartinm7 commented 6 months ago

Hi!!

I'm trying to do a PUT request with a body. I'm specifying the schema as the documentation says, but it seems like the body validation is not doing anything. ¿any idea?

Here are my json files.

the impostor:

  {
    "request": {
      "method": "PUT",
      "endpoint": "/v1/users/123/country",
      "schemaFile": "schemas/put-update-account.json"
    },
    "response": {
      "headers": {
        "Content-Type": "application/json"
      },
      "status": 204
    }
  }

the schema file

{
  "country": {
    "type": "string",
    "enum": [
      "SPANISH",
      "ENGLISH"
    ]
  },
  "required": [
    "country"
  ]
}

the test request

{
  "in": {
    "method": "PUT",
    "url": "http://localhost:8090/v1/users/123/country",
    "body": "{\"country\":\"SPANISH\"}"
  },
  "out": {
    "status_code": 204,
    "header": {
      "Content-Type": ["application/json"]
    }
  }
}

my krakenD definition

{
  "endpoint": "/v1/users/{userId}/country",
  "method": [
    "PUT"
  ],
  "output_encoding": "no-op",
  "backend": [
    {
      "host": [
        "http://my-micro"
      ],
      "encoding": "no-op",
      "url_pattern": "/v1/users/{userId}/country",
      "circuit_breaker": {
        "enabled": true,
        "timeout": 2000.0
      }
    }
  ]
}

Thanks in advance

joanlopez commented 6 months ago

Hi @amartinm7,

I have tested your example and it seems to be working correctly, as expected.

What do you see as output when you start Killgrave? 🤔 Make sure that Killgrave is loading correctly your imposters:

Thanks!

amartinm7 commented 6 months ago

Hi @joanlopez

The previous example is working, but it's not taking account the schema and the body. I mean, if you change the request body with "body": "{\"country\":\"FRANCE\"}"... the test is working too... but you expect an error!!. This is my point, the validation is not executed. I don't know why.

joanlopez commented 6 months ago

Sorry 🙏🏻 Yes, you're right. I assumed the schema you shared was a "subset" of the entire file.

But, if it still fails, I guess it's probably because that's literally your whole file, and I think the problem is that your JSON Schema definition is not completely correct. It should be something like:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "country": {
      "type": "string",
      "enum": [
        "SPANISH",
        "ENGLISH"
      ]
    }
  },
  "required": [
    "country"
  ]
}

Technically you can omit the $schema field, but you should:

I have tried it with that, and it works as expected.

Thanks, and apologies for the confusion!

amartinm7 commented 6 months ago

Hi @joanlopez

Using the schema as you say, it's working. So thank you very much for your help :)

But when I'm sending the "body": "{"country":"FRANCE"}" in request, or empty body, I'm getting a 404 error message.

I think the error should be a 400 Bad Request, doesn't it? I mean, It's a validation error more than if the resource exists or not.

Thxs in advance

joanlopez commented 6 months ago

Hi @amartinm7,

By default, Killgrave returns a 404 Not Found for any non-covered endpoint. There has been some discussions about having the possibility of defining a fallback behavior, but so far is not possible.

However, you can still use Killgrave to achieve the behavior you expect with the following imposters definition:

[
  {
    "request": {
      "method": "PUT",
      "endpoint": "/v1/users/123/country",
      "schemaFile": "schemas/put-update-account.json"
    },
    "response": {
      "headers": {
        "Content-Type": "application/json"
      },
      "status": 204
    }
  },
  {
    "request": {
      "method": "PUT",
      "endpoint": "/v1/users/123/country"
    },
    "response": {
      "headers": {
        "Content-Type": "application/json"
      },
      "status": 400
    }
  }
]

So, basically, you're defining an imposter to respond to PUT /v1/users/123/country requests that satisfy your schema with 204 No Content, and another one to respond to PUT /v1/users/123/country requests with 400 Bad Request. So, if you order them (remind that order matters!) as in the example above, the correct requests will satisfy the schema, and fall into that imposter (returning a 204 No Content), while the incorrect requests will fall to the second imposter (returning a 400 Bad Request) , which has no requirements other than the method and the path.

I hope that helps you!

amartinm7 commented 6 months ago

Hi @joanlopez

Yes, it helps. Thxs a lot! :)