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? - openapi

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.

Related

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"

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...

API gateway blocking requests with content in body

I'm trying to post a request through AWS API gateway with postman.
I have aws IAM on and it appears to be working. I can send a request with nothing in the body I get a 200 response back from my lambda function.
I would like to send a binary file in the body however whenever I add anything, form-data, raw or binary data to the body of the request I get this message:
{
"message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been\n'POST\ ..."
}
I have tried adding
image/png and application/octect-stream to Binary Media Types
and also tried specifying a model with just one field in it and that doesn't work either.
Any help would be much appreciated. I tried posting on AWS forums but there is no "post", "ask a question" or "create" button to actually ask a question, so back to old trusty stackoverflow.
Cheers. Mitch.
Edit API gateway setup:
openapi: 3.0.1
info:
title: AlarmEndpoints
version: '2019-03-02T03:22:39Z'
servers:
- url: https://602wer34n1.execute-api.ap-southeast-2.amazonaws.com/{basePath}
variables:
basePath:
default: /dev
paths:
/alarm/message:
post:
responses:
'200':
description: 200 response
content:
application/json:
schema:
$ref: '#/components/schemas/Empty'
security:
- sigv4: [
]
x-amazon-apigateway-integration:
uri: arn:aws:apigateway:ap-southeast-2:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-southeast-2:962000000000:function:alarm_message/invocations
responses:
default:
statusCode: '200'
passthroughBehavior: when_no_match
httpMethod: POST
contentHandling: CONVERT_TO_TEXT
type: aws
components:
schemas:
Empty:
title: Empty Schema
type: object
securitySchemes:
sigv4:
type: apiKey
name: Authorization
in: header
x-amazon-apigateway-authtype: awsSigv4
x-amazon-apigateway-policy:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
AWS: arn:aws:iam::962000000000:user/alarm_user
Action: execute-api:Invoke
Resource: arn:aws:execute-api:ap-southeast-2:962000000000:*/*/*
Lambda Function:
import json
import os
import boto3
def lambda_handler(event, context):
var = os.environ.get("a_variable")
return {
'statusCode': 200,
'body': json.dumps({'message': 'Hello from Lambda 2!',
'echo': event,
'data': var})
}

Validate OpenAPI response with dredd

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

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"