Questions:
IntegrationResponse to Sam template ? Is it possible without OpenApi?
Way to add headers to GatewayResponses in SAM template?
What im trying to achive:
Define gateway responses and integration responses inside a SAM
CloudFront template.
What i checked so far:
SAM github link
SAM issue
I was checking SAM github but for me it wasnt clear how to do it based on the above link.
Also i didnt found any answer on stackoverflow which would explain why the headers are bad in my gatewayresponse snippet
Every Help is appreciated
Some examples:
Globals:
Api:
GatewayResponses:
MISSING_AUTHENTICATION_TOKEN:
ResponseParameters:
# gatewayresponse.header.Cache-Control: "no-cache"
ResponseTemplates:
"application/json" : '{"errors": [{errorKey: "error Value"}]}'
StatusCode: '404'
#defaultResponse: true
Expected function level integrationResponse:
Function:
Type: AWS::Serverless::Function
Properties:
Handler: Function.handler
Timeout: 20
CodeUri: "src/Function"
Role: .......
Events:
FunctionGet:
Type: Api
Properties:
Path: /Function
Method: get
IntegrationResponse:
SOME_ERROR_CODE
ResponseTemplates
integrationresponse.header
So long story short half of my question is stupid. in proxy integration API GW is by defult returning the response from server to client no need further declaration in SAM template.
As for the headers the following way is the correct:
Globals:
Api:
GatewayResponses:
MISSING_AUTHENTICATION_TOKEN:
ResponseParameters:
Headers:
Access-Control-Allow-Origin: "'*'"
Access-Control-Allow-Headers: "'*'"
Cache-Control: "'no-cache'"
Content-Type: "'application/json'"
ResponseTemplates:
"application/json" : '{"errors": [{errorKey: "error Value"}]}'
StatusCode: '404'
#defaultResponse: true
Related
I have an HTTPApi API Gateway created with the Serverless Framework. But for some routes, the CORS is not working.
provider:
name: aws
runtime: nodejs12.x
stage: dev
region: us-west-2
timeout: 29
httpApi:
cors:
allowedOrigins:
- '*'
allowedMethods:
- GET
- OPTIONS
- POST
- PUT
- DELETE
allowedHeaders:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
- X-Amz-User-Agent
- X-Transaction-Key
- Access-Control-Allow-Origin
I tried setting the cors:true option on the provider but still doesnt work.
This is the response returned on all routes wether it is 4xx or 2xx codes.
return {
statusCode: StatusCode,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials" : true,
"Access-Control-Allow-Headers" : "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET,PUT,DELETE"
},
body: JSON.stringify(Res, null, 2),
};
If I check the console I can see that the options are indeed applied
However, some routes actually work
And some others don't, the ones that don't work have the X-Transaction-Key header and the OPTIONS does not return the access-control-allow-headers: authorization,content-type,x-amz-date,x-amz-security-token,x-amz-user-agent,x-api-key,x-transaction-key header
What am I missing?
Thanks in advance
I have faced a similar problem. After 3 days of pulling my hair. I have found my problem. Everything was ok except, In my client, there were few wrong URLs(spelling mistakes) pointing to my server API. This is why few API was ok and few of them not working properly.
After fixing to the right URL everything is ok. Here is my learning, hope someday it will help others:
Check you're serverless.yml file's cors section, here is an example
cors:
origin: '*'
headers:
- Content-Type
- X-Amz-Date
- Authorization
- X-Api-Key
- X-Amz-Security-Token
allowCredentials: false
Check Lamdba for proper response header as question contains
Additional Tools for troubleshooting:
https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-cors-errors/
https://aws.amazon.com/premiumsupport/knowledge-center/support-case-browser-har-file/
https://toolbox.googleapps.com/apps/har_analyzer/
Hope it will be helpful, Thanks!
Happy Coding
Have you tried fixing the 'cors: true' value in the function event as in Serverless with cors ?
I am using Serverless and I have a lambda that is available via API Gateway. Like many of the CORs questions that mention a similar stack, I am getting the following error when making a call from a browser (usual Postman/curl local testing works just fine):
Access to XMLHttpRequest at 'https://<gatewayUrl>/dev/login/?userType=userA' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field z-client-timezone is not allowed by Access-Control-Allow-Headers in preflight response
The Integration Request type is Lambda_Proxy
Cors has been enabled, adding the Options Method
The lambda handler returns the expected headers
The axios request sends one custom header Z-Client-Timezone that is also allowed in the Lambda
I've tried everything including everything here, but no luck.
I'm extremely frustrated so any help would be awesome. One more thing, when I do curl -i -X OPTIONS https://<gatewayUrl>/dev/login I get this result, which seems to be missing Z-Client-Timezone:
HTTP/2 200
content-type: application/json
content-length: 0
date: Fri, 10 Jul 2020 04:00:10 GMT
x-amzn-requestid: <aws_requestId>
access-control-allow-origin: *
access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
x-amz-apigw-id: <apigw-id>
access-control-allow-methods: OPTIONS,POST
via: 1.1 <id>.cloudfront.net (CloudFront), 1.1 <id>.cloudfront.net (CloudFront)
x-amz-cf-pop: DFW50-C1
x-cache: Miss from cloudfront
x-amz-cf-pop: DFW55-C1
x-amz-cf-id: <cf-id>
My Lambda:
export async function login(event) {
const headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
}
....
return {
statusCode: 200,
headers,
body: JSON.stringify(session)
};
}
My Serverless.yml:
login:
handler: dist/src/handlers/auth.login
events:
- http:
path: login
method: post
cors:
origin: '*'
headers:
- Access-Control-Allow-Credentials
resources:
Resources:
GatewayResponseDefault4XX:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
ResponseParameters:
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
ResponseType: DEFAULT_4XX
RestApiId:
Ref: 'ApiGatewayRestApi'
I would love any help you can give. I've omitted some code as everything else works except for the cors stuff so I've just included that but if more clarification is needed, I'm happy to provide.
While your lambda function is allowing the Z-Client-Timezone header, the built-in options method of AWS is not.
In order to allow this, you can do the following -
login:
handler: dist/src/handlers/auth.login
events:
- http:
path: login
method: post
cors:
origin: '*'
headers:
- Access-Control-Allow-Credentials
- Z-Client-Timezone
Then add any other headers you are also sending.
I'm trying to create a function with CORS enabled.
The function works as expected using Postman (cors headers present), but I get CORS error when trying from a browser (no cors header).
const getTicket = async event => {
var ticketNumber = Date.now();
return {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Methods': '*',
'Access-Control-Allow-Origin': '*',
},
statusCode: 200,
body: JSON.stringify({"ticketNumber": ticketNumber})
};
};
functions:
getTicket:
handler: code/common/ticket.getTicket
runtime: nodejs12.x
events:
- http:
method: get
path: getTicket
cors: true
authorizer:
arn: ${self:custom.auth0.authorizer_arn}
I also tried few more ways of writing the serverless.yaml file, but none of them worked, the only difference between them being the created methods in my API Gateway. Sometimes I got GET+OPTIONS methods, sometimes only GET, but never worked with CORS.
I get the error:
"Access to XMLHttpRequest at 'https://...amazonaws.com/prod/getTicket' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
What you are likely seeing is that the server is returning an error before it reaches your return statements. In other words, API Gateway is returning a 502 or 403 (as these are the most common errors), and those specific returns have no CORS headers present by default in API Gateway. I would recommend using CloudWatch to inspect the specific Lambda invocations to determine if your Lambda function itself is erroring out and correct that.
You can also force your API Gateway to return the CORS headers for all responses. In the resources section of the serverless.yml file you can do the following and add any additional entries for other status codes:
resources:
Resources:
GatewayResponseDefault4XX:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
ResponseParameters:
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
ResponseType: DEFAULT_4XX
RestApiId:
Ref: 'ApiGatewayRestApi'
Solved
The below issue was simply caused by the body property of the response object constructed in my Lambda. I was forgetting to stringify the data, returning body: data instead of body: JSON.stringify(data). This problem with the response appeared to trigger an error with API Gateway which caused the request failures with some rather confusing error messages.
Problem
I'm working on a ecommerce site using React, Serverless and the Stripe API. My front-end React app is making a GET request using Axios to my Lambda function which has been exposed via API Gateway. The Lambda function in turn queries the Stripe API and returns the Stripe response data to my React app. However, I am experiencing CORS issues as my React app tries to call the Lambda, it receives the following error:
Failed to load: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 502.
Querying the Lambda endpoint in Insomnia returns a 502 response with { "message": "internal server error" }. But executing the serverless invoke command from the Lambda function from the terminal successfully returns the Stripe data.
I am enabling cors for the function in my serverless.yml file and including 'Access-Control-Allow-Origin': '*' in my Lambda code response as advised in this Serverless blog post, I have also attempted adding a various combinations of the following headers to my Lambda response and my Axios request based on suggestions found on this issue on Axios and this issue on Serverless. I've deleted and redeployed the service multiple times and
Lambda response headers
headers: {
'Access-Control-Expose-Headers': 'Access-Control-Allow-Origin',
'Access-Control-Allow-Credentials': true,
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
React/Axios config
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
crossDomain: true
}
Currently my code is as follows:
React app
import Axios from 'axios';
import { GET_PRODUCTS_URL } from '../config';
export default () => {
return Axios
.get(GET_PRODUCT_URL, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
crossDomain: true
})
.then(({ data }) => data)
.catch(console.log);
}
Lambda
import Stripe from 'stripe';
const apiKey = process.env.STRIPE_SECRET_KEY;
const stripe = Stripe(apiKey);
module.exports.handler = (event, context, callback) => {
return stripe.products
.list()
.then(({ data }) => {
const response = {
statusCode: 200,
headers: {
'Access-Control-Expose-Headers': 'Access-Control-Allow-Origin',
'Access-Control-Allow-Credentials': true,
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: data,
};
callback(null, response);
})
.catch(console.log);
}
Serverless.yml
service: srd
provider:
name: aws
runtime: nodejs6.10
stage: ${opt:stage, self:custom.defaultStage}
region: eu-west-1
memorySize: 256
timeout: 6
versionFunctions: true
plugins:
- serverless-plugin-optimize
- serverless-plugin-scripts
package:
individually: true
functions:
get-products:
handler: lambda/get-products.handler
name: srd-get-products-${self:provider.stage}
description: 'get srd products from stripe'
environment:
STRIPE_PUBLISHABLE_KEY: ${self:custom.stripe_publishable_key.${self:provider.stage}}
STRIPE_SECRET_KEY: ${self:custom.stripe_secret_key.${self:provider.stage}}
events:
- http:
path: products
method: get
cors: true
custom:
defaultStage: dev
stripe_publishable_key:
dev: ${file(env.yml):STRIPE_DEV_PUBLISHABLE_KEY}
live: ${file(env.yml):STRIPE_LIVE_PUBLISHABLE_KEY}
stripe_secret_key:
dev: ${file(env.yml):STRIPE_DEV_SECRET_KEY}
live: ${file(env.yml):STRIPE_LIVE_SECRET_KEY}
I've been at this for hours, any insights much appreciated.
Edit/Additional
Making an options request from the CLI returns the following:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Date: Mon, 19 Mar 2018 06:52:12 GMT
x-amzn-RequestId: 0d10c9d1-2b42-11e8-b270-a723e367048e
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent
Access-Control-Allow-Methods: OPTIONS,GET
Access-Control-Allow-Credentials: false
X-Cache: Miss from cloudfront
Via: 1.1 e40b14deb4a844594f746b751f632677.cloudfront.net (CloudFront)
X-Amz-Cf-Id: eMvu3Ke7m7GNFCFgIOGVJmoObFwYMeEt4o8AByoipfMn1nXIi9Vo0g==
The HTTP response code in the CORS error message says 502. This means the server you are requesting is unavailable.
In an event of a 502, the browser cannot make successful OPTIONS requests, so even if your CORS setup in the server is correct, you will still get a CORS error since it was not resolved properly.
Look at your server and make sure it is running as it should. Once the 502 error is fixed, try again and you should be good to go. Try making a manual OPTIONS request, similar to that of what the browser would make, and see if you get the same error.
I would like to download a PDF file using a nodejs lambda function deployed in AWS. Please let me know the configurations to be provided in serverless settings.yaml file.
I am able to download PDF by making below configuration changes from console.
1) Add Content-Type as application/pdf 2) Map the response model for application/pdf=>Empty 3) Change the content handling in integration response from passthrough (default) to Convert to Binary. I am looking for options where these can be provided in serverless configuration file
I am looking for options where content handling and response model can be set using serverless
Below is the snippet from serverless.yml
events:
- http:
path: /test
method: get
integration: lambda
response:
statusCodes:
200:
pattern: '' # Default response method
headers:
Content-Type: "'application/pdf'"
In your lambda function, you have to return a json object like that:
{
statusCode: 200,
headers: { 'Content-Type': 'application/pdf' },
body: YOUR_PDF_base64_encoded_string,
isBase64Encoded: true, // important
};
then, you can use serverless-apigw-binary plugin to config APIGateway Binary Support or you can do it by manualy: Change APIGateway setting
use application/pdf instead of my image mime types.