API Gateway validator not validating schema of integer query parameter - aws-api-gateway

I have a limit query string parameter that can be in the range of 1 to 100. I'm trying to enforce that range in my OpenAPI 3.0 spec as follows. But instead, through the API Gateway Console Test Feature, I am able to pass any value and any values outside the range (even letters) won't raise an error. I tried making the limit required, but the same occurs. I am not have trouble validating request bodies.
Does anyone know how to resolve this ?
openapi: 3.0.0
...
paths:
/clients:
get:
summary: List clients
operationId: listClients
description: List clients.
parameters:
- in: query
name: limit
required: false
schema:
type: integer
default: 10
minimum: 1
maximum: 100
description: Maximum number of items to return.
...
x-amazon-apigateway-request-validator: params
...
x-amazon-apigateway-request-validators:
params:
validateRequestParameters: true
validateRequestBody: false
body:
validateRequestParameters: false
validateRequestBody: true
params and body:
validateRequestParameters: true
validateRequestBody: true
UPDATE: I also tried removing default: 10 but without success.

Related

How to define a header parameter with multiple attributes in OpenAPI 3.0?

I need to define a header parameter like this X-Custom: id1=uuid1;id2=uuid3
Since this is a common header for all paths I want to define it once and reference it every time. So far I came up with this:
openapi: 3.0.3
components:
parameters:
customHeader:
name: "X-Custom"
in: header # <--- produces error
required: true
schema:
type: object
properties:
id1:
type: string
format: uuid
id2:
type: string
format: uuid
style: matrix
explode: true
But I get an error that 'header' is not allowed and the parameter does not show up in the preview.
Any idea what's wrong?
OpenAPI 3 supports only style: simple for header parameters. This means that objects can be serialized in one of two ways:
# {"id1": "uuid1", "id2": "uuid2"} becomes...
# explode: false
X-Custom: id1,uuid1,id2,uuid2
# explode: true
X-Custom: id1=uuid1,id2=uuid2
Note that none of these styles match your expected format X-Custom: id1=uuid1;id2=uuid2 with ; as a separator. In fact, OpenAPI currently does not have a way to define ;-separated header values.
The most you can do is define the entire header as a string, mention the header value format in the description, and provide an example value:
customHeader:
name: X-Custom
in: header
required: true
schema:
type: string
example: id1=uuid1;id2=uuid2
There are existing feature requests to improve header serialization styles in OpenAPI:
Support for structured-headers de/serialization
Make it easier to define link headers
If you are designing a new API rather than documenting an existing one, another workaround is to split the header into two headers:
X-id1: uuid1
X-id2: uuid2

OpenAPI 3: How to require one or more properties in PATCH requestBody?

I have a User resource:
I want to define a PATCH /users/{uid} so that the client can update image, bio or both.
An example valid request body would be:
{
"image": "filename.jpg",
"bio": "My biography"
}
If the image property is sent alone the existing bio property will remain the same on the server and only the image will be updated. If both are sent (as above) both will change.
In short:
an empty request body {} is disallowed.
{"image": "new.jpg"}, {"bio": "new bio" or {"image": "new.jpg", "bio": "new bio" is allowed.
This is what I have so far. I'm using the anyOf object with two separate type: objects within. I've tried this with Swagger hub using the virtserver, but the virtual server always seems to return 200 OK and passes back the example data regardless of whatever is passed, so I have no way to know.
Does my definition do what I intended? If not, what the best practice?
openapi: 3.0.0
...
patch:
summary: update a user
parameters:
- in: path
name: uid
description: user id
schema:
type: string
required: true
requestBody:
description: Update a user's profile
content:
application/json:
schema:
type: object
anyOf:
- type: object
properties:
image:
type: string
- type: object
properties:
bio:
type: string
additionalProperties: false
required: true
responses:
'200':
description: Successfully updated
content:
application/json:
schema:
$ref: '#/components/schemas/User'
You can use minProperties: 1:
requestBody:
description: Update a user's profile
content:
application/json:
schema:
type: object
properties:
image:
type: string
bio:
type: string
minProperties: 1 # <-----------
additionalProperties: false
or anyOf + required:
type: object
properties:
image:
type: string
bio:
type: string
anyOf: # <-----------
- required: [image]
- required: [bio]
additionalProperties: false
Your original example defines an empty object {} because:
Without required or minProperties defined, all properties are optional.
More importantly, additionalProperties: false only knows about the properties defined directly alongside it and has no visibility into subschemas. So, in this example it disallows ALL properties.
As for:
I've tried this with SwaggerHub using the VirtServer, but the virtual server always seems to return 200 OK and passes back the example data regardless of whatever is passed.
This is because SwaggerHub mocks do not validate inputs and always return a static response based on the response schema.
From SwaggerHub documentation:
Note that the mock does not support business logic, that is, it cannot send specific responses based on the input.
...
The mock generates static responses for each API operation based on its responses and the response media types defined in the spec.
If an operation has multiple response codes, the mock returns the response with the lowest status code. For example, if an operation has responses 201, 202 and 400, the mock returns the 201 response.

OpenAPI optional object default value

Suppose you have the following OpenAPI requestBody specification:
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
field1:
type: number
default: 1
field2:
type: object
properties:
subfield:
type: number
default: 2
The request body contains:
a number field with default value 1
an object field, containing itself a number field with default value 2
If a client sends an empty payload, we should agree that field1 value is supposed to be 1, but what about field2 value?
field2 is not specified, so it must be considered as null
field2 should be an object build with default values: {subfield: 2}
OpenAPI does not answer this question and that's up to me to decide what my application should do
Correct behaviour would be your alternative 1, with a twist.
field2 should be considered to be "not present" and not null as there is some difference between those cases, see https://github.com/OAI/OpenAPI-Specification/issues/1775 for some discussion related to that difference.
From a validation point-of-view field2 is not declared as nullable an object like {"field2": null} should not be valid, but {} would be.
Whether "not present" or null should be handled differently is up to your application.

define common parameters for openapi/swagger annotations

On https://swagger.io/docs/specification/describing-parameters/ (OAS3) there is an example for common parameters which can be refered by $ref in paths and operations:
components:
parameters:
offsetParam: # <-- Arbitrary name for the definition that will be used to refer to it.
# Not necessarily the same as the parameter name.
in: query
name: offset
required: false
schema:
type: integer
minimum: 0
description: The number of items to skip before starting to collect the result set.
limitParam:
in: query
name: limit
required: false
schema:
type: integer
minimum: 1
maximum: 50
default: 20
description: The numbers of items to return.
paths:
/users:
get:
summary: Gets a list of users.
parameters:
- $ref: '#/components/parameters/offsetParam'
- $ref: '#/components/parameters/limitParam'
responses:
'200':
description: OK
/teams:
get:
summary: Gets a list of teams.
parameters:
- $ref: '#/components/parameters/offsetParam'
- $ref: '#/components/parameters/limitParam'
responses:
'200':
description: OK
How would I declare Swagger Annotations to produce this output, especially if the parameters are primitive type?
I tried
#Schema(type = "int")
#OpenAPIDefinition(info = #Info(description = "descr"))
public class OffsetParam {
public static final String DESCRIPTION =
"The number of items to skip before starting to collect the result set.";
#Parameter(description = "desc1")
public static OffsetParam valueOf(String value) {
return null;
}
}
but I only got
"components" : {
"schemas" : {
"OffsetParam" : {
"type" : "object"
},...
Do you have any idea which v3 annotations to add to a JAX-RS 2.1 resource?
My goal is to define those common parameters once and refer to them in all resources across my application.

Specify an array of strings as body parameter in swagger API

I would like to post an array of strings like
[
"id1",
"id2"
]
to a Swagger based API. In my swagger file, I have those lines:
paths:
/some_url:
post:
parameters:
- name: ids
in: body
required: true
What is the correct way to specify the type of ids as an array of strings?
Update:
According to the specification, the following should work in my option:
parameters:
- in: body
description: xxx
required: true
schema:
type: array
items:
type: string
https://github.com/Yelp/swagger_spec_validator does not accept it and returns a long list of convoluted errors, which look like the code expects some $ref.
Your description of an array of string is correct, but the parameter definition misses the name property to be valid.
Here's a full working example:
swagger: "2.0"
info:
title: A dummy title
version: 1.0.0
paths:
/path:
post:
parameters:
- in: body
description: xxx
required: true
name: a name
schema:
type: array
items:
type: string
responses:
default:
description: OK
Try the online editor to check your OpenAPI (fka. Swagger) specs: http://editor.swagger.io/
I have created a swagger issue as the help provided by Arnaud, although is valid yaml, will give you NPE exceptions when trying to generate. You will need to provide an object like the following:
myDataItem:
type: object
description: A list of values
required:
- values
properties:
values:
type: array
items:
type: string
And then refer to it (in your post item etc):
schema:
$ref: "#/definitions/myDataItem"
For reference the github issue:
https://github.com/swagger-api/swagger-codegen/issues/6745
Note, the issue has been fixed in version 2.3.0 and higher, ideally you should upgrade to that version.
None of the answers worked for me. As it is stated in the following Baeldung article:
To better document the API and instruct the user, we can use the example label of how to insert values
So the full working example would be something like that:
swagger: "2.0"
info:
title: A dummy title
version: 1.0.0
paths:
/path:
post:
parameters:
- in: body
description: xxx
required: true
name: a name
schema:
type: array
items:
type: string
example: ["str1", "str2", "str3"]
responses:
default:
description: OK
You can check how the Example Value is now better informed in the Swagger editor.
For Array containing Object as it's content, definition for Object can be also expressed using definitions & $ref.
Example:
schema:
type: array
items:
$ref: '#/definitions/ObjectSchemaDefinition'
definitions:
ObjectSchemaDefinition:
type: string
The answer with the most votes got me in the right direction. I just needed an example of an array of objects where each one of them had a property which was an array of strings with more than one value in the strings array. Thanks to the documentation I got it working like this:
MyObject:
type: object
properties:
body:
type: array
items:
type: object
properties:
type:
type: string
values:
type: array
items:
type: string
example:
- type: "firstElement"
values: ["Active", "Inactive"]
- type: "SecondElement"
values: ["Active", "Inactive"]
One thing to keep in mind is that indentation is of paramount importance to swagger. If you don't indent things well, swagger will give you strange error messages.