Validate OpenAPI response with dredd - openapi

I have an OpenAPI v3 specification file with the following (showing just fragments):
paths:
/global/name:
get:
description: Some description
tags:
- Global settings
operationId: getGlobalSettingsName
responses:
# Response code
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/globalSettingsName'
components:
schemas:
globalSettingsName:
type: object
properties:
name:
type: integer
description: 'ID'
example: 1
required:
- name
but the server response is:
{
"name": "somestring"
}
Note the name property type is integer and in the server response, it is a string (on purpose) but dredd request passes (success).
Doesn't dredd check for response property types?
I redefined the response as string (not JSON):
responses:
# Response code
'200':
description: Successful response
content:
application/json:
schema:
type: string
and dredd doesn't complain about either.
I even changed the property of the schema:
globalSettingsName:
type: object
properties:
www:
type: string
description: 'some description'
example: 'somestring'
required:
- www
And same (success) result when it is expected to fail.
Aren't these validation supported by dredd? Am I using specification wrong?

It results that the current version (8.0.5) only supports example value in content: https://github.com/apiaryio/dredd/issues/1281

Related

How to correctly specify OpenAPI 3 Link object based on response header

I am working on a REST API defined by an OpenAPI specification document; one thing that is currently missing is the use of Links to define the connection options between endpoints, and I can't figure out how to specify what I want.
For example, imagine a POST /widgets endpoint that returns a 201 Created response, and sets the URI of the created widget in the Location response header. My definition is currently something like this:
paths:
/widgets:
post:
operationId: addWidget
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AddWidget'
responses:
'201':
headers:
Location:
$ref: '#/components/headers/Location'
'400':
$ref: '#/components/responses/BadRequest'
/widgets/{widgetId}:
get:
operationId: getWidgetById
parameters:
- $ref: '#/components/parameters/WidgetId'
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Widget'
The OpenAPI documentation (https://swagger.io/docs/specification/links/) shows how to get the raw value of the Location header, but that's a URI, and the body of the 201 response is empty e.g.
links:
getWidgetById:
operationId: getWidgetById
parameters:
employeeId: '$response.headers.location'
So how can I extract e.g. a GUID from Location: https://my.api.com/widgets/3a32d587-56ca-4dea-81b4-01ed9cdf41c0/ to insert that into the employeeId parameter for the link?

How do I generate a cut-down version of an OpenAPI spec YML (ex. petsore.yaml) using the file itself?

I'd like to use the OpenAPI generator to generate a cut-down version of a OpenAPI spec .yml to build a Postman-esque web application reading these cut-down versions.
Here's an example on what I try to get. I take the standard Petstore spec as an example:
Petstore:
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
'200':
description: A paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
should generate a fairly similar cut-down spec file looking like this:
- url: /pets
method: GET
title: string
body: null
queryParameters:
- name: limit
defaultValue: 1
required: false
pathVariables: [ ]
- url: /pets/{{petId}}
method: GET
title: string
body: null
queryParameters: [ ]
pathVariables:
- name: petId
defaultValue: 1
required: true
- url: /pets
method: POST
title: string
body: "{ \"id\": \"1\", \"name\": \"Cathy\"}"
queryParameters: [ ]
pathVariables: [ ]
I never worked with mustache templates and didn't find any simple ELI5 tutorials of how to do that and if it's even possible, but I'd need that for multiple API specs as it would be too much of an effort to do and maintain it for every API manually.
How would I go about doing that? Is OpenAPI the right choice or should I go with something different?

How to vary requestBody type based on a path parameter in OpenAPI 3.0?

In OpenAPI 2.0, in: body and in: formData parameters cannot exist together for the same operation, according to Swagger send body and formData parameter and OpenAPI 2.0 Specification. That makes sense.
But I'm using OpenAPI 3.0 and I wonder if there is a way to switch requestBody according to a path parameter? When store is path1, requestBody should use content with application/json; when store is path2, requestBody should use content with multipart/form-data.
/customs/{store}:
post:
description: Customs server calls Nomad to receive the filing result of one
order
operationId: post_customs_callback
parameters:
- description: ID of the store.
explode: true
in: path
name: store
required: true
schema:
type: string
style: simple
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties: # Request parts
openReq:
type: string
# application/json:
# schema:
# type: string
description: Order details
OpenAPI Specification does not have a way to vary request/response body based on specific parameter values. However, in your scenario you can use two non-parameterized paths instead – /customs/path1 for JSON requests and /customs/path2 for multipart requests.
openapi: 3.0.0
...
paths:
/customs/path1:
post:
...
requestBody:
required: true
content:
application/json:
schema:
...
/customs/path2:
post:
...
requestBody:
required: true
content:
multipart/form-data:
schema:
...

Why does Swagger mark the GET requests as duplicate mapping ke?

I have this 2 GET requests one is /report and the second one is /report/{id}.
paths:
/report:
get:
operationId: getReportsList
responses:
'200':
description: List of reports
content:
application/json:
schema:
items:
$ref: '#/components/schemas/Metadata'
get:
operationId: getReportById
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: Report is finished and returned
content:
application/json:
schema:
$ref: '#/components/schemas/Report'
SwaggerHub shows an error against second GET with a description
duplicated mapping key
Could you tell me what am I doing wrong and why Swagger does think that URLs with and without path variable are the same?
Add a new path where explicitly append your path variable /report/{id} for the second GET.

REST API using a RAML specification: how to specify total-pages in response

I am not sure about how the REST API should be designed in terms of pagination.
Here's my example:
#%RAML 1.0
title: Test Api Documentation
description: Test Api Documentation
baseUri: https://localhost/
version: v0.1
protocols: [ HTTPS ]
mediaType: [ application/json ]
documentation:
- title: Test API for REST Client
content:
"Test API for REST Client."
types:
Thing:
type: object
properties:
name: string
age: number
color: string
Things:
type: object
properties:
things?: Thing[]
totalPages?:
type: integer
format: int64
/things:
get:
headers:
Cookie:
type: string
responses:
'200':
description: OK
body:
application/json:
type: Things
'401':
description: Unauthorized
'404':
description: Not Found
queryParameters:
page:
description: page
required: false
type: integer
format: int32
pageSize:
description: pageSize
required: false
type: integer
format: int32
There is this wrapper type 'Things' to be able to add the totalpages property for the response.
Is this the right way how to do it?
I've also read that a custom http header can be used (x-total-pages or something like that).
I actually kind of don't like to have all the wrapper types in the API...
Does anybody know which is the standard for this?
Thanks a lot in advance for your answers.
Sergio
You can encapsulate all the paginated traits into a trait and use that across all you pageable reosources using is. As pageable resource are typically GET /collectionresource, you can also add a trait for the response header X-TOTAL-PAGES for 200 responses that are paginated.
Example:
#%RAML 1.0
baseUri: https://mocksvc.qax.mulesoft.com/mocks/8ab3d909-11e0-4f1d-aaef-bef029b83fbf
title: paginated api
mediaType: application/json
protocols: [ HTTP ]
traits:
paginated:
queryParameters:
page:
description: page
required: false
type: integer
format: int32
pageSize:
description: pageSize
required: false
type: integer
format: int32
responses:
200:
headers:
x-total-pages:
types:
Thing:
type: object
properties:
name: string
age: number
color: string
Things:
type: object
properties:
things?: Thing[]
/things:
get:
is: [ paginated ]
responses:
'200':
description: OK
body:
application/json:
type: Things
'401':
description: Unauthorized
'404':
description: Not Found