API gateway blocking requests with content in body - aws-api-gateway

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})
}

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?

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

Serverless AWS ApiGateway methodresponse

I've a question about Serverless and API Gateway
I have a function in my serverless.yml like this :
getAccount:
handler: functions/account/handlers.getAccount
events:
- http:
path: account
method: get
cors: true
authorizer: authorize
But i need to add something by the API Gateway interface :
API Gateway expected
I want to add this directly in my serverless file with something like that
getAccount:
handler: functions/account/handlers.getAccount
events:
- http:
path: account
method: get
cors: true
authorizer: authorize
methodresponse:
code : 200
header : "Access-Control-Allow-Origin"
body :
content-type : "application/json"
model : Empty
Does someone can tell me the syntax for serverless.yml to add this in my file ?
Thank you
Please find below Serverless Sample code for Method Responses.
Please let me know how you go.
getAccount:
handler: functions/account/handlers.getAccount
events:
- http:
path: account
method: get
cors: true
authorizer: authorize
methodResponses:
-
statusCode: "200"
responseBody:
description: "Response body description"
responseHeaders:
-
name: "x-superheader"
description: "this is a super header"
responseModels:
"application/json": "CreateResponse"
-
statusCode: "400"
responseModels:
"application/json": "ErrorResponse"

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