stoplightio / prism

Turn any OpenAPI2/3 and Postman Collection file into an API server with mocking, transformations and validations.

Home Page:https://stoplight.io/open-source/prism

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Wrong validation of request body with integer type property

jinyoung opened this issue · comments

Context

I have this oas3.0 definition with request body with properties in integer type:

---
paths:
  '/inventories/{id}/update':
    summary: decrease stock operation on inventories
    put:
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                productId:
                  description: productId of this DecreaseStock
                  type: integer
                qty:
                  description: qty of this DecreaseStock
                  type: integer
            examples:
              Example 0:
                value:
                  productId: 123
                  qty: 10
              Example 1:
                value:
                  productId: 456
                  qty: 50
              Example 2:
                value:
                  productId: 789
                  qty: 150
      parameters:
        - examples:
            '1':
              value: 1
          name: id
          description: DecreaseStock name
          schema:
            type: integer
          in: path
          required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Inventory'
              examples:
                Example 0:
                  value:
                    stock: 20
                    productId: 123
                Example 1:
                  value:
                    stock: 30
                    productId: 456
                Example 2:
                  value:
                    stock: 30
                    productId: 789
          description: DecreaseStock Operation
      operationId: DecreaseStock
      summary: DecreaseStock
      description: DecreaseStock

openapi: 3.0.2
info:
  title: Inventory
  version: 0.0.1
  description: API definition of inventory
  contact:
    name: creator's name
    url: 'http://creator.homepage.address'
    email: creator@creator.com
  license:
    name: MIT License
    url: 'https://opensource.org/licenses/MIT'
components:
  schemas:
    Inventory:
      title: Root Type for Inventory
      description: The root of the Inventory type's schema.
      type: object
      properties:
        productId:
          description: productId of this Inventory
          type: integer
        stock:
          description: stock of this Inventory
          type: integer
      example:
        productId: 1
        stock: 1
tags:
  - name: Inventory
    description: Inventory resource

Current Behavior

It returns the request validation error like this:

 $ http put  :4010/inventories/1/update  productId=456 qty=50 prefer:"validate-request=false, valid
ate-response=false"
HTTP/1.1 422 Unprocessable Entity
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: *
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: *
Connection: keep-alive
Content-Length: 496
Date: Mon, 16 Oct 2023 18:01:18 GMT
Keep-Alive: timeout=5
content-type: application/problem+json

{
    "detail": "Your request is not valid and no HTTP validation response was found in the spec, so Prism is generating this error for you.",
    "status": 422,
    "title": "Invalid request",
    "type": "https://stoplight.io/prism/errors#UNPROCESSABLE_ENTITY",
    "validation": [
        {
            "code": "type",
            "location": [
                "body",
                "productId"
            ],
            "message": "Request body property productId must be integer",
            "severity": "Error"
        },
        {
            "code": "type",
            "location": [
                "body",
                "qty"
            ],
            "message": "Request body property qty must be integer",
            "severity": "Error"
        }
    ]

Expected Behavior

It should return the matching example with no validation errors

Possible Workaround/Solution

When I change the property types to 'string', it works.

Steps to Reproduce

  1. save above openapi as openapi.yaml
  2. launch mock server:
npx @stoplight/prism-cli@latest mock openapi.yaml
  1. install Httpie with 'pip install httpie'
  2. request the put method example
http put  :4010/inventories/1/update  productId=456 qty=50 prefer:"validate-request=false, validate-response=false"

Environment

I was suspicious myself, so I did some additional testing based on the officially obtained open API example from the Microcks:

https://raw.githubusercontent.com/microcks/microcks/master/samples/APIPastry-openapi.yaml

I tried :

  1. launch the mock service with above openapi 3 spec:
npx @stoplight/prism-cli@latest mock https://raw.githubusercontent.com/microcks/microcks/master/samples/APIPastry-openapi.yaml
  1. list api works well:
$ http :4010/pastry
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: *
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: *
Connection: keep-alive
Content-Length: 378
Content-type: application/json
Date: Tue, 17 Oct 2023 00:51:50 GMT
Keep-Alive: timeout=5

[
    {
        "description": "Delicieux Baba au Rhum pas calorique du tout",
        "name": "Baba Rhum",
        "price": 3.2,
        "size": "L",
        "status": "available"
    },
    {
        "description": "Delicieux Divorces pas calorique du tout",
        "name": "Divorces",
        "price": 2.8,
        "size": "M",
        "status": "available"
    },
    {
        "description": "Delicieuse Tartelette aux Fraises fraiches",
        "name": "Tartelette Fraise",
        "price": 2,
        "size": "S",
        "status": "available"
    }
]
  1. the get api for specific id works well too, but the expected example (the matching response would be value of 'Millefeuille') wasn't returned but the default example was returned
$ http :4010/pastry/Millefeuille
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: *
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: *
Connection: keep-alive
Content-Length: 113
Content-type: application/json
Date: Tue, 17 Oct 2023 00:52:31 GMT
Keep-Alive: timeout=5

{
    "description": "A short description os my pastry",
    "name": "My Pastry",
    "price": 4.5,
    "size": "M",
    "status": "available"
}
  1. the patch api returns wrong validation too. (price must be number even if I gave the 10.5 which is proper number input with httpie)
$ http patch  :4010/pastry/M
illefeuille price=10.5

HTTP/1.1 422 Unprocessable Entity
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: *
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: *
Connection: keep-alive
Content-Length: 372
Date: Tue, 17 Oct 2023 00:54:22 GMT
Keep-Alive: timeout=5
content-type: application/problem+json

{
    "detail": "Your request is not valid and no HTTP validation response was found in the spec, so Prism is generating this error for you.",
    "status": 422,
    "title": "Invalid request",
    "type": "https://stoplight.io/prism/errors#UNPROCESSABLE_ENTITY",
    "validation": [
        {
            "code": "type",
            "location": [
                "body",
                "price"
            ],
            "message": "Request body property price must be number",
            "severity": "Error"
        }
    ]
}

Hi @jinyoung, it looks like the default behavior for httpie is to pass variables as strings according to their documentation. In order to pass a body param as an integer you have to use the := syntax. So you're actually sending Prism a string and not an integer for those body params, so Prism's response is correct and expected. You can also use the --print option as outlined here to see what request you're actually sending Prism.