-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
apigateway: add explicit support for CORS #906
Comments
From @kennu: function addCorsOptions(apiResource: apigateway.IRestApiResource) {
const options = apiResource.addMethod('OPTIONS', new apigateway.MockIntegration({
integrationResponses: [{
statusCode: '200',
responseParameters: {
'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
'method.response.header.Access-Control-Allow-Origin': "'*'",
'method.response.header.Access-Control-Allow-Credentials': "'false'",
'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE'",
},
}],
passthroughBehavior: apigateway.PassthroughBehavior.Never,
requestTemplates: {
"application/json": "{\"statusCode\": 200}"
},
}))
const methodResource = options.findChild('Resource') as apigateway.cloudformation.MethodResource
methodResource.propertyOverrides.methodResponses = [{
statusCode: '200',
responseModels: {
'application/json': 'Empty'
},
responseParameters: {
'method.response.header.Access-Control-Allow-Headers': true,
'method.response.header.Access-Control-Allow-Methods': true,
'method.response.header.Access-Control-Allow-Credentials': true,
'method.response.header.Access-Control-Allow-Origin': true,
},
}]
} |
I am also currently struggling with this. How do you actually use the provided code snippet? Add it to the root of the api? Or for every Resource I want to enable CORS for? I currently have something like:
With what variables to I have to call addCorsOptions and at which point? I tried on the root and on blogs, but couldn't get it to work yet. |
I have attached it to the API root and any resource paths like this:
You should be able to verify after deployment in API Gateway Console that everything is present. But you also need to return an (I do wish API Gateway could handle all of this automagically with a single enable option.. It's been very complicated from the beginning.) |
Thanks, that worked! |
Example provided by @kennu stopped working for the latest version of the CDK. However, after some changes following code is working for me: function addCorsOptions(apiResource: apigateway.IRestApiResource) {
const options = apiResource.addMethod('OPTIONS', new apigateway.MockIntegration({
integrationResponses: [{
statusCode: '200',
responseParameters: {
'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
'method.response.header.Access-Control-Allow-Origin': "'*'",
'method.response.header.Access-Control-Allow-Credentials': "'false'",
'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE'",
},
}],
passthroughBehavior: apigateway.PassthroughBehavior.Never,
requestTemplates: {
"application/json": "{\"statusCode\": 200}"
},
}))
const methodResource = (options as cdk.Construct).node.findChild("Resource") as apigateway.CfnMethod
methodResource.propertyOverrides.methodResponses = [{
statusCode: '200',
responseModels: {
'application/json': 'Empty'
},
responseParameters: {
'method.response.header.Access-Control-Allow-Headers': true,
'method.response.header.Access-Control-Allow-Methods': true,
'method.response.header.Access-Control-Allow-Credentials': true,
'method.response.header.Access-Control-Allow-Origin': true,
},
}]
} As a hint if you get 500 status on contentHandling: apigateway.ContentHandling.ConvertToText |
Hello, I am trying to implement something similar, but in Java. I unfortunately cannot get past the The Java implementation is not letting me cast the Any Java experts out there who might be able to lend a hand? Thanks in advance! |
I can't help but I am looking forward to #1572 be resolved and merged. |
@piotrkubisa thank you for the note and reference to the issue. I'll be keeping an eye out for that issue as well! |
The I'm not really sure how to work around this now. Any ideas? |
I think you can now specify the method responses as an option to addMethod() export function addCorsOptions(apiResource: apigateway.IRestApiResource) {
apiResource.addMethod('OPTIONS', new apigateway.MockIntegration({
integrationResponses: [{
statusCode: '200',
responseParameters: {
'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
'method.response.header.Access-Control-Allow-Origin': "'*'",
'method.response.header.Access-Control-Allow-Credentials': "'false'",
'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE'",
},
}],
passthroughBehavior: apigateway.PassthroughBehavior.Never,
requestTemplates: {
"application/json": "{\"statusCode\": 200}"
},
}), {
methodResponses: [{
statusCode: '200',
responseParameters: {
'method.response.header.Access-Control-Allow-Headers': true,
'method.response.header.Access-Control-Allow-Methods': true,
'method.response.header.Access-Control-Allow-Credentials': true,
'method.response.header.Access-Control-Allow-Origin': true,
},
}]
})
} |
Oh nice one, thanks 👍 |
This is not working. Broken in 0.37.0 ? |
What is not working? What is the error you are seeing? |
Just a few edits:
|
Works like a charm |
Just curious why it's MockIntegration. It feels weird to put that in a production config |
@eladb I'm using LambdaRestApi and when I try to add this - it simply remove the lambda integration.... how to add CORS in this case ? const APIGW = new apigw.LambdaRestApi(this, 'ListBranchesAPIGW', { |
thanks every one on this thread for the code samples. Finally, I successfully, deployed an API Gateway + Lambda Proxy with COGNITO Authorizer - sharing the code - might help someone who lands here..
|
@smfontevan, this is super helpful. I have a CFn stack where I assign a function to each resource's method (or at least to each resource), but the [ Haven't fully tested yet (waiting on CloudFront distro delete/create), but this has helped understand the non-swagger/AWS:SERVERLESS was of creating an API gateway. EDIT: code formatting |
We are planning to implement this feature on a live Twitch stream next week: https://www.twitch.tv/events/4tjzcuGeSymHA5UCn-MbrA Would love to have you guys over for real time feedback and inputs! |
It would be great if the API would allow modifying the origins (and maybe methods?) to support the following setup:
|
The OPTIONS request can (should?) return |
@spaceemotion not sure I understand the requirement. Wouldn't that just mean specifying |
Yes. I just thought I'd mention it since you said you'd want to implement the feature next/this week. Not sure what that entails, but setting the origin via props would be nice. Setting it by hand using the methods described above works like a charm. |
Cool, yeah. Obvsiouly users should be able to specify the allowed origin(s). |
For anybody interested, I managed to setup Gateway response for custom authorizer (when access is denied) with
The only problem I have with this solution is that changes to |
(1) What is the recommended way of enabling CORS pre-flight for APIG + Lambda proxy integration with the latest CDK? (I am using It seems that const api = new LambdaRestApi(this, "Api", {
defaultCorsPreflightOptions: {
allowOrigins: ["https://example.com"]
},
// ...other props
}); I think the answer to (1) is, "Yes, use (2) However, does the recommendation change when an authorization type is added? As shown below, I have included IAM authorization which is also applied to the OPTIONS method. Unfortunately, this violates the CORS pre-flight contract or, at least, guarantees it will fail b/c the pre-flight OPTIONS request will not have credentials (per my understanding). const api = new LambdaRestApi(this, "Api", {
defaultCorsPreflightOptions: {
allowOrigins: ["https://example.com"],
allowCredentials: true
},
defaultMethodOptions: {
authorizationType: AuthorizationType.IAM
},
// ...other props
}); Is there a way to "remove" the authorization type for a specific method (or set to NONE). More generally speaking, can the methods of a REST resource be mutated post-construction? Alternatively, is there ever a valid case to restrict OPTIONS? (I'm still new to this, but I only see CORS pre-flight mentioned on MDN's OPTIONS doc.) If there are not use cases, can we update the APIG construct to not apply (ignore) the authorization type to OPTIONS methods? In the mean-time, I'm going to continue use the hand-rolled solution. Thanks for the details on this thread so far everyone. |
I'm having the same issue, in SAM this was fixed while ago with a flag AddDefaultAuthorizerToCorsPreflight. |
@connorjs What's the hand-rolled solution you're talking about? I tried the @smfontevan solution with no success (I'm still having CORS issues) |
@leantorres73 @connorjs can you please raise a new issue so we can track this properly and get it fixed. It's harder for us to track as comments on a closed issue. |
@connorjs I have Cognito + API Gateway + Proxy integration + CORS working. It's not a real proxy anymore, but until there is an easy solution to disable security in OPTIONS, this is a way to go const proxy = api.root.addProxy({
defaultIntegration: new apigateway.LambdaIntegration(handler),
anyMethod: false
});
const authorizerConfig = {
authorizer: {
authorizerId: authorizer.ref
},
authorizationType: apigateway.AuthorizationType.COGNITO
};
proxy.addMethod('GET', undefined, authorizerConfig);
proxy.addMethod('POST', undefined, authorizerConfig);
proxy.addMethod('PUT', undefined, authorizerConfig);
addCorsOptions(proxy); |
Can you please a separate GitHub issue on this? |
Requirements
resource.addCorsPreflight(options)
AllowOrigin
AllowHeaders
with defaults for API GatewayAllowMethods
AllowCredentials
MaxAge
ExposeHeaders
Vary
response headerLambdaRestApi
(apply a CORS policy to all routes)AWS::ApiGateway::GatewayResponse
Nice to Have
Non-Requirements
Resources
Notes
Coming from stack overflow
Note that we get a lot of confusion around this since it only configures the Preflight request. Customers expect it to be a magic setting for enabling CORS headers on their Lambda responses. We cant do this because API Gateway does not allow response header mapping for Lambda proxy. Might be better to call this CorsPreflight? At minimum document it clearly.
The text was updated successfully, but these errors were encountered: