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
- save above openapi as openapi.yaml
- launch mock server:
npx @stoplight/prism-cli@latest mock openapi.yaml
- install Httpie with 'pip install httpie'
- request the put method example
http put :4010/inventories/1/update productId=456 qty=50 prefer:"validate-request=false, validate-response=false"
Environment
- Version used: @latest version today
- Environment name and version (e.g. Chrome 39, node.js 5.4):
- Operating System and version (desktop or mobile): Ubuntu
- Link to your environment/workspace/project: https://github.com/jinyoung/testmodel or you can try it inside a gitpod :
https://gitpod.io/#github.com/jinyoung/testmodel
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 :
- 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
- 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"
}
]
- 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"
}
- 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.