I'm using AWS Lambda function setup with the API Gateway. I have been trying to set-cookies to the application but even though it shows in the console headers, it is not setting up in the browser.
callback(null, {
statusCode: 302,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
'Location': "https://example.com",
'Set-Cookie': cookieString,
'Content-Type': 'application/json'
},
body: null
} );
https://aws.amazon.com/blogs/compute/simply-serverless-using-aws-lambda-to-expose-custom-cookies-with-api-gateway/
Tried implementing this but in the browser cookies were not set.
Try to set the Path of your cookie:
Set-Cookie:myCookie=foo; Path=/; HttpOnly
After changing the s3 bucket hosted static website to an API gateway, cookies passed
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Cookies.html
Related
I have an application written in React JS, running on localhost, which makes API calls to API Gateway in AWS. API Gateway forwards requests to a lambda function, which returns a response. I have enabled CORS on AWS side.
At the moment whenever I click a 'request' button in the application I get a response from the gateway. Here is my current python code:
import json
def lambda_handler(event, context):
response = {}
response['result'] = "Success"
response['message'] = "Updated successfully!"
return {
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
},
"body": json.dumps(response)
}
And here's the body of the request:
{
"ID": "1101",
"RequestDate": "2021-02-28"
}
This works fine. I get the 'message' value from this response and can display it without problems.
Next I want to display the information containing some data coming from the request. For example instead of Updated successfully I would like to get the RequestDate from the request and return Updated successfully on 2021-02-28.
I added these two lines:
def lambda_handler(event, context):
body = json.loads(event['body'])
request_date = body['RequestDate']
response = {}
response['result'] = "Success"
response['message'] = "Updated successfully!"
return {
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
},
"body": json.dumps(response)
}
As soon as I make this change I get the following code in my application:
Access to fetch at url from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
This only happens when I add request_date = body['RequestDate']. I tried returning the body only and it was working fine as well.
In my react js application I add following headers as well:
async callAPI(url, method, data) {
let result = await fetch(url, {
method: method,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({
data
})
})
return result.json().then(body => this.notify(body['message']));
}
I tried enabling CORS and deploying the resource again but to no avail. I have added Access-Control-Allow-Origin to allowed headers in AWS. As I mentioned it works fine with post method prior to adding that one line. What could be wrong here and how can I remedy it?
EDIT:
One more thing. I get this error only from my application running on localhost. Curling or using any REST client works fine.
EDIT2:
Added fetch code
Setting up CORS in Lambda is dependent on how you setup API Gateway. API Gateway has several modes [REST, HTTP, WebSocket]. In the case of REST, API Gateway does some pre-processing on the incoming request like parameter validation before passing to Lambda. HTTP Proxy is just that, a pass through to Lambda, and Websockets is not really for this discussion.
I am assuming it is because you are using API Gateway in standard configuration and you have not enabled CORS on API Gateway. The code you provided above will work for API Gateway Configured for HTTP.
If you are using the CDK, or CloudFormation then you must configure CORS there, else the easiest is to use the console.
Go to your API in the AWS Console, select resources, select your method or service, from the actions menu enable CORS. And then publish your updated API.
Here is a link to the AWS documentation that outlines how to do it.
Some advice, when testing endpoints via a browser it is best not to use Localhost or 127.0.0.1 it has unintended consequences. Edit your hosts file and give yourself a domain name, and use that domain name instead.
CORS is there for a reason to prevent Cross Site Scripting or Cross Site Origin Attacks. Try not to use *, testing sure, but production no. If you have code say on S3, and your REST services on say API Gateway you can front both with CloudFront using the same Origin, and let CloudFront know to forward based on URL (e.g /API) to APIGateway and the other to S3. Thus everything has the same domain.
This is what I have on my server and it works fine. Using fetch on the front-end.
Server Code:
import json
result = {"hello": "world"}
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "*"
},
'body': json.dumps(result)
}
Front-end Code using ES6
url = "Your url"
path = "Your desired path"
data = {"hello": "world"}
const response = await fetch(url + path, {
method: "POST",
cache: "no-cache",
mode: "cors",
body: JSON.stringify(data),
});
Add statusCode inside response from lambda
return {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
},
'body': json.dumps(response)
}
In case there is any error in your lambda it will return default 5XX response without any CORS headers and in such cases browser will complain for cors headers not found.
You can add your current code in try block and in except block you can print the error and return some default response like below
return {
'statusCode': 500,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST'
},
'body': json.dumps({'message':'Unexpected error'})
}
Add some log statements in your lambda and check api gateway configuration for Lambda proxy setting.
Make sure you check your api gateway logs and lambda function logs for some more details regarding error.
I am calling API using react.js application. I am getting error from AWS API Gateway about CORS policy:
Access to XMLHttpRequest at 'https://awsapigatewayid.execute-api.ap-south-1.amazonaws.com/staging/top10' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
From React App code for call api like:
let options = {
url: `https://awsapigatewayid.execute-api.ap-south-1.amazonaws.com/staging/top10`,
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Req-Time': getCurrentTimestamp(),
'Access-Control-Allow-Origin': '*',
},
data: data || {},
};
if (isAuthorised) {
options.headers['X-Auth-Token'] = 'usertokengoeshere';
}
const response = await axios(options);
My API from AWS API Gateway:
You need to remove the 'Access-Control-Allow-Origin': '*', from your API call, to solve your error, instead add it to your Lambda response. Preferably not with '*' but with your actual Origin.
I am trying to send a fetch request to AWS API gateway but it keeps giving me this error. I am doing it from the admin side in WordPress.
Access to fetch at
'https://34557322456.execute-api.ap-southeast-1.amazonaws.com/V1/code?kdata=something' from origin 'https://mywebsite.online' has been blocked by CORS
policy: Response to preflight request doesn't pass access control
check: No 'Access-Control-Allow-Origin' header is present on the
requested resource. If an opaque response serves your needs, set the
request's mode to 'no-cors' to fetch the resource with CORS disabled.
This is the request
fetch('https://34557322456.execute-api.ap-southeast-1.amazonaws.com/V1/code?kdata=something', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
}).then(response => {
return response.json()
})
.then(data => console.log(data))
.catch(error => console.log(error));
Please help
The headers should be on the server side, try something like this in your .php file:
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: 'X-Requested-With,content-type'");
header("Access-Control-Allow-Methods: 'GET, POST, OPTIONS, PUT, PATCH, DELETE'");
I'm trying to connect my a React Application to a Django Server. The React application is running on http://127.0.0.1:3000/
The response headers has Access-Control-Allow-Origin: http://127.0.0.1:3000 set, yet I am still seeing the error.
I am currently using Django's corsheaders package as recommended everywhere. Decent example of the recommendation How can I enable CORS on Django REST Framework.
But I have also tried custom middleware at this point.
My Django Settings.py file contains the following
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
Django is on 8000, React on 3000
CORS_ORIGIN_WHITELIST = [
'http://127.0.0.1:3000',
'http://localhost:3000',
'http://127.0.0.1:8000',
'http://localhost:8000',
]
My request in react looks like this. (It works when I run it directly, not through the browser)
const fetch = require('node-fetch')
const response = await fetch(
url,
{
json: true,
method: 'GET',
headers: {
'Access-Control-Allow-Origin': '*',
Accept: '*/*',
'Content-Type': 'application/json'
}
}
)
Again, it is so strange that I am making the request from http://127.0.0.1:3000 and the response headers has Access-Control-Allow-Origin: http://127.0.0.1:3000 but for some reason it is still failing.
Oh the error message in the browsers console is
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/query/?date=2019-10-25. (Reason: missing token ‘access-control-allow-origin’ in CORS header ‘Access-Control-Allow-Headers’ from CORS preflight channel).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/query/?date=2019-10-25. (Reason: CORS request did not succeed).
Any help would be awesome! Thanks
#sideshowbarker figured it out. It was because I was sending headers in my request.
Changing
const fetch = require('node-fetch')
const response = await fetch(
url,
{
json: true,
method: 'GET',
headers: {
'Access-Control-Allow-Origin': '*',
Accept: '*/*',
'Content-Type': 'application/json'
}
}
)
to
const fetch = require('node-fetch')
const response = await fetch(
url,
{
json: true,
method: 'GET'
}
)
Immediately fixed the issue! Thank you!
I've wasted all day on this one. For some reason this works with method GET but when I try it with method PUT I get
No 'Access-Control-Allow-Origin' header is present on the requested resource
I've enabled CORS via API Gateway and Deployed the API. My response contains
return {
'statusCode': statusCode,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Methods': 'POST,GET,OPTIONS,PUT',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps(body),
'isBase64Encoded': False
}
My jquery looks like this
var options = {};
options['url'] = URL;
options['method'] = METHOD;
options['contentType'] = 'application/json';
options['headers'] = { 'x-api-key': KEY }
$.ajax(options).done(...
Ended up nothing was wrong with the API Gateway my lambda wasn't returning what I thought it was.