Dredd verification response body and headers - rest

I have similar openapi.yml spec file:
openapi: 3.0.1
info:
title: some title
version: "4"
paths:
/users/{userId}/data:
get:
summary: some summary
description: some description
operationId: userData
parameters:
- name: some-token
in: header
description: desc
required: true
schema:
type: string
example: "tokenExample"
...
- name: userId
in: path
description: desc
required: true
schema:
type: string
example: "someID"
responses:
"200":
description: desc
content:
"application/json":
schema:
$ref: '#/components/schemas/DataModel'
components:
schemas:
DataModel:
type: object
properties:
data1:
type: integer
format: int32
data2:
type: integer
format: int32
data3:
type: integer
format: int32
Test execution giving me such result:
request:
method: GET
uri: /users/<someID>/data
headers:
some-token: 389fe056-e904-48fd-8d89-caaf8769ab84
...
User-Agent: Dredd/14.0.0 (Linux 5.10.104-linuxkit; x64)
body:
expected:
headers:
Content-Type: application/json; charset=utf-8
body:
{
"data1": 0,
"data2": 0,
"data3": 0
}
statusCode: 200
actual:
statusCode: 200
headers:
server: Apache-Coyote/1.1
set-cookie: rememberMe=deleteMe; Path=/somepath; Max-Age=0; Expires=Thu, 17-Nov-2022 08:41:46 GMT; Secure
content-type: application/json;charset=UTF-8
transfer-encoding: chunked
date: Fri, 18 Nov 2022 08:41:46 GMT
connection: close
bodyEncoding: utf-8
body:
{
"data1": 0,
"data2": 0,
"data3": 0
}
Body and status code matched perfectly, but something, maybe headers, failing verification. How can I get passed verification for this test? Is headers matching necessary for passing test? If yes, how achieve headers matching?
PS. I now that is very similar question already on Stackoverflow, but it was asked pretty long time ago, so I decided to refresh it and some more details.

Running dredd with debug log level (--logLevel=debug) helped me to recognize the problem. That needed to be exactly "application/json;charset=utf-8" in content response, instead of "application/json"

Related

What is the reason of request body not matching the schema?

I'm using swagger to describe a simple endpoint to upload file with date(int64). There is request body:
put:
tags:
- files
description: Add an associated file to a project
operationId: addFile
parameters:
- name: projectId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
content:
multipart/form-data:
schema:
$ref: "#/components/schemas/AddFileToProjectRequestBody"
required: true
responses:
200:
description: Successful
content: {}
and schema:
AddFileToProjectRequestBody:
required:
- file
type: object
properties:
file:
type: string
format: binary
description: The file to upload
fileDate:
type: integer
format: int64
minimum: 0
description: File modified date (Unix timestamp in milliseconds)
If I upload a simple file it works fine. But if I am trying to add a fileDate I get an error.
"request body has an error: doesn't match the schema: Error at "/fileDate": Field must be set to integer or not be present"
Looks like it fails to read number as int. Can someone explain to me why? I have tried to change it to string and it worked, but doesn't look logical to me to set date as string.
UPD:
------WebKitFormBoundaryGs2
Content-Disposition: form-data; name="fileDate"
1670485649000
------WebKitFormBoundaryGs2
Content-Disposition: form-data; name="projectFile"; filename="1.txt"
Content-Type: text/plain
------WebKitFormBoundaryGs2--

Open API 3 - add headers on individual content-type in responses

I have my spec which have a path with a 200 response code, that response code can access multiple content-types, I want to add the Content-Disposition Header to one of those content-types.
Here's a sample:
openapi: '3.0.3'
info:
...
servers:
...
paths:
/examples:
...
get:
...
responses:
'200':
content:
application/json:
...
application/pdf:
encoding:
file:
headers:
Content-Disposition:
schema:
type: string
example: attachment; filename="name.pdf"
examples:
file:
summary: File
externalValue: https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf
Here's the generated view:
no header
Here is an example where the header is added (for another endpoint)
responses:
'201':
description: Success
headers:
Location:
schema:
type: string
format: uri
description: The URI to the newly created example
And here's the generated view for that one:
with header
Am I doing something wrong?
encoding.<name>.headers is used to define headers for individual parts of a multipart/* request body, which is different from your scenario. Since your response is not multipart/*, the response headers must be defined in responses.<code>.headers.
However, OpenAPI does not have a way to vary response headers per media type. What you can do is define the Content-Disposition response header as optional and explain that it only applies to applicatioln/pdf responses.
paths:
/examples:
get:
responses:
'200':
description: ok
content:
application/pdf:
schema:
type: string
format: binary
headers:
Content-Disposition:
schema:
type: string
description: Used only with `application/pdf` responses
example: attachment; filename="name.pdf"

In OpenAPI 3, how to document that an Accept header with a specified value is necessary on request in order for a successful API call?

For a legacy API that I document in order for a successful authentication I need to provide the following headers:
X-Access-Token: {token}
Accept: application/json; version=public/v2
For the token part I need document it via:
openapi: 3.0.0
info:
version: "v2"
title: Company App Public Api
description: Integrate your platform with company app website
components:
securitySchemes:
ApiKey:
type: 'apiKey'
in: 'header'
name: 'X-Access-Token'
security:
- ApiKey: []
But how I can document that also for an authentication I need to provide an Accept: application/json; version=public/v2. The Accept header must contain the application/json; version=public/v2 anything else returns 406 Not Acceptable header.
Also, the header Accept with value application/json; version=public/v2 should be in my request. The response header is always application/json.
Do you know how I can document that?
In OpenAPI 3.0, the request header Accept and the response header Content-Type are both defined as responses.<code>.content.<Accept value>. This needs to be defined in every operation.
paths:
/something:
get:
responses:
'200':
description: Successful operation
content:
'application/json; version=public/v2': # <-----
schema:
...
'406':
description: Invalid media type was specified in the `Accept` header (should be `application/json; version=public/v2`)
In order to specify that you should perform a http request using the application/json; version=public/v2 accept header you should document it like this:
openapi: 3.0.0
info:
version: "v2"
title: Company App Public Api
description: Integrate your platform with company app website
components:
securitySchemes:
ApiKey:
type: 'apiKey'
in: 'header'
name: 'X-Access-Token'
responses:
406:
description: "Is returned once `Accept` header has not been provided or does not contain the `application/json; version=public/v2` value."
content:
'application/json':
schema:
type: object
properties:
error:
type: 'boolean'
type:
type: 'string'
message:
type: 'string'
description: "Your access token is either missing or incorrect. Please check the X-Access-Token header and try again."
401:
description: "Is returned once `X-Access-Token` has not been provided"
content:
'application/json':
schema:
type: object
properties:
error:
type: 'boolean'
type:
type: 'string'
message:
description: "Your access token is either missing or incorrect. Please check the X-Access-Token header and try again."
security:
- ApiKey: []
paths:
/myendpoint:
put:
requestBody:
required: true
content:
'application/json; version=public/v2': {}
responses:
200:
'application/json':
#your response jhere as documented in
406:
$ref: '#/components/responses/406'
401:
$ref: '#/components/responses/401'
So with this approach you tell in the documentation that the request should be a put one with the Accept header application/json; version=public/v2 with any (or no) parameters.
Though for get requests requestBody is not a valid definition.

AWS API Gateway: error Invalid mapping expression parameter specified: method.response.header.access-control-allow-origin

For the first time in the last years with AWS API Gateway I got this strange blocking error, that can kills production environment: in one day many of my responses (not all) lost their Access-Control-Allow-Origin header. In web UI I also see that they are not exists. But they are still exists in exported Swagger file. And more than that - I cannot set any value, for '*' or 'https://example.com' I am getting error:
Invalid mapping expression specified: Validation Result: warnings :
[], errors : [Invalid mapping expression parameter specified:
method.response.header.access-control-allow-origin]
This is from yesterday (I did not change anything to get this defect), looks like horrible bug of AWS that blocks our development (main product is no longer available without CORS headers). And now I am afraid to use AWS API Gateway for production environment...
I tried to remove header in Method Response and add again, through the same web UI.
This is exported Swagger - for the same part as in screenshot. Here you can see my method.response.header.Access-Control-Allow-Origin. So in browser UI and exported file are not the same!
paths:
/lineupmaps:
get:
consumes:
- "application/json"
produces:
- "application/json"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
headers:
Access-Control-Allow-Origin:
type: "string"
security:
- cognito: []
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:988646599334:function:getLineUpMap/invocations"
responses:
default:
statusCode: "200"
responseParameters:
method.response.header.access-control-allow-origin: "'https://happy-marketer.gms-ai.com'"
responseTemplates:
application/json: "$input.body"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
requestTemplates:
application/json: "{\n \"specs\": $input.params('specs'),\n \"competitors\"\
: $input.params('competitors'),\n \"numberOfModels\": $input.params('numberOfModels')\n\
}"
contentHandling: "CONVERT_TO_TEXT"
type: "aws"
options:
consumes:
- "application/json"
produces:
- "application/json"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
headers:
Access-Control-Allow-Origin:
type: "string"
Access-Control-Max-Age:
type: "string"
Access-Control-Allow-Headers:
type: "string"
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
responseParameters:
method.response.header.Access-Control-Max-Age: "'86400'"
method.response.header.Access-Control-Allow-Headers: "'Authorization'"
method.response.header.Access-Control-Allow-Origin: "'https://happy-marketer.gms-ai.com'"
passthroughBehavior: "when_no_match"
requestTemplates:
application/json: "{\"statusCode\": 200}"
type: "mock"
Tried to import exported Swagger, also with commented/removed responseParameters block: still the same error:
Thank you nachary: helped importing of my Swagger with removed method.response.header.access-control-allow-origin in the GET of one endpoint...

Swagger Validator complaining about seemingly well-formed request

I'm using the swagger-express-validator to validate inputs to a small API server (using Swagger 2 format)
My path definition is as follows
/api/v1/users:
post:
produces:
- "application/json"
parameters:
- in: body
name: ids
description: Array of user ids to be processed
required: true
schema:
$ref: "#/definitions/ArrayOfIds"
responses:
200:
description: success
ArrayOfIds is defined as follows
Id:
type: string
ArrayOfIds:
type: array
items:
$ref: "#/definitions/Id"
Sending a post request to the server as follows:
POST /api/v1/users HTTP/1.1
Content-Type: application/json
Accept: application/json
Host: localhost:3000
Connection: close
User-Agent: Paw/3.1.7 (Macintosh; OS X/10.13.6) GCDHTTPRequest
Content-Length: 35
{
"ids": ["abcd12345"]
}
Results in an error
Request Invalid: POST /api/v1/users
[ { keyword: 'type',
dataPath: '',
schemaPath: '#/type',
params: { type: 'array' },
message: 'should be array' } ]
I am however able to access req.body.ids in my Express route controller code and it contains the correct value ['1234abc'].
Do you have any idea as to why the validator is complaining about the request? It looks fine to me.
Your request body does not match the definition. According to the definition, the array in the request body must be unwrapped:
POST /api/v1/users HTTP/1.1
Content-Type: application/json
...
["abcd12345"]
If the array needs to be wrapped into the ids wrapper property, the request body should be defined as type: object with the property ids that contains the array:
parameters:
- in: body
name: ids
description: Array of user ids to be processed
required: true
schema:
type: object
properties:
ids:
$ref: "#/definitions/ArrayOfIds"