I am calling an AWS API which uses lambda function. I am calling it from a HTML page which is hosted in S3 (static web hosting). While calling the API I get CORS error:
Access to XMLHttpRequest at '' from origin
'' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I have tried it after enabling CORS on API, Specifying CORS on S3 bucket but it is not working.
Seems, I am missing the right place where CORS headers are to be specifies.
Additional information:
I get following information in chrome developer tool
**Response Headers**
content-length: 42
content-type: application/json
date: Mon, 24 Feb 2020 04:28:51 GMT
status: 403
x-amz-apigw-id: IYmYgFQvoAMFy6Q=
x-amzn-errortype: MissingAuthenticationTokenException
x-amzn-requestid: 79b18379-383d-4ddb-a061-77f55b5727c3
**Request Headers**
authority: apiid-api.us-east-1.amazonaws.com
method: POST
path: /Prod
scheme: https
accept: application/json, text/javascript, */*; q=0.01
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,hi;q=0.8
access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
access-control-allow-methods: GET, OPTIONS
access-control-allow-origin: https://apiid.execute-api.us-east-1.amazonaws.com/Prod
content-length: 117
content-type: application/json; charset=UTF-8
origin: http://example.com
referer: http://example.com/
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36
Lambda function code:
var AWS = require('aws-sdk');
var ses = new AWS.SES();
var RECEIVER = 'example#gmail.com';
var SENDER = 'example#gmail.com';
var response = {
"isBase64Encoded": false,
"headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'},
"statusCode": 200,
"body": "{\"result\": \"Success.\"}"
};
exports.handler = function (event, context) {
console.log('Received event:', event);
sendEmail(event, function (err, data) {
context.done(err, null);
});
};
function sendEmail (event, done) {
var params = {
Destination: {
ToAddresses: [
RECEIVER
]
},
Message: {
Body: {
Text: {
Data: 'name: ' + event.name + '\nphone: ' + event.phone + '\nemail: ' + event.email + '\ndesc: ' + event.desc,
Charset: 'UTF-8'
}
},
Subject: {
Data: 'Website Referral Form: ' + event.name,
Charset: 'UTF-8'
}
},
Source: SENDER
};
ses.sendEmail(params, done);
}
No 'Access-Control-Allow-Origin' header is present on the requested resource.
This is saying that the resource you requested, your Lambda via API Gateway, is not returning an Access-Control-Allow-Origin header in its response; the browser is expecting the CORS headers in the response from the API (possibly because of an OPTIONS request), but the response doesn’t have them.
You’ve not said so specifically but I’m assuming you’re using a Lambda proxy integration on your API gateway. To solve your issue, add a Access-Control-Allow-Origin: * header to the response your Lambda returns. You’ve not specified the language your Lambda is written in, or provided your Lambda code, but if it was in NodeJS, a snippet of what you‘d return might look something like:
const result = {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
// other required headers
},
body: object_you_are_returning
};
return result;
Very surprisingly, the reason seems to be “the client-side shouldn't have 'Access-Control-Allow-Origin': '*'. That should only be in the Lambda code, apparently, and adding it to the jQuery code will cause the preflight to fail for some reason.”
https://github.com/serverless/serverless/issues/4037#issuecomment-320434887
Supplement information following the comment:
I also tried to use ajax hosted in S3 to call my Lambda function through API Gateway. I have tried many suggestions especially this solution (http://stackoverflow.com/a/52683640/13530447), but none of them works for me. In the developer-mode of Chrome, I kept seeing the error "Access to XMLHttpRequest at '[my API]' from origin '[my S3 website]' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response." I solved this by removing 'Access-Control-Allow-Origin': '*' in ajax. Still take the solution (http://stackoverflow.com/a/52683640/13530447) as an example, it will work by changing
$.ajax(
{
url: 'https://npvkf9jnqb.execute-api.us-east-1.amazonaws.com/v1',
headers: {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'
},
crossDomain: true,
type:'GET',
dataType: 'text',
success: function(data)
{
window.alert(data);
}
});
into
$.ajax(
{
url: 'https://npvkf9jnqb.execute-api.us-east-1.amazonaws.com/v1',
headers: {'Content-Type': 'application/json'},
crossDomain: true,
type:'GET',
dataType: 'text',
success: function(data)
{
window.alert(data);
}
});
Related
I'm having trouble making a post request to a lambda function with axios in my web app. I get back the error message "Access to XMLHttpRequest at 'lambdalink' from origin 'http://localhost:4200' 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."
Code for the axios request:
const config = {
method: 'post',
url: 'lambdalink',
headers: {
'Access-Control-Allow-Origin': '*',
},
data: {
info: JSON.stringify(data)
}
};
Axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
When I make the request without the data param in the config the request goes through just fine, but once I add data to it I get that error. My CORS configuration for the lambda function is as follows:
Access-Control-Allow-Origin:
"*", "http://localhost:4200/", "http://localhost:4200"
Access-Control-Allow-Headers:
"access-control-allow-origin"
Access-Control-Allow-Methods:
"POST"
I've tried different combinations of these settings, but no luck. Am I missing something server side or am I just not handling CORS correctly in the browser?
I'm trying to authenticate against couchdb using this documentation
When I do
# first request
const url = 'http://localhost:5984/_session'
fetch(url, {
method: 'POST',
headers: {
"Content-Type": "application/json",
},
body : JSON.stringify({
"name": "my_username",
"password": "my_password"
}),
}).then( data => {
console.log(data)
}).catch(e => {
console.log('Error', e)
})
If one of my_username or my_password IS NOT right i get:
body: (...)
bodyUsed: false
headers: Headers {}
ok: false
redirected: false
status: 401
statusText: "Unauthorized"
type: "cors"
url: "http://localhost:5984/_session"
which is fine.
But, if one of my_username or my_password IS right i get:
body: ReadableStream
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://localhost:5984/_session"
instead of
HTTP/1.1 200 OK
Cache-Control: must-revalidate
Content-Length: 43
Content-Type: application/json
Date: Mon, 03 Dec 2012 01:23:14 GMT
Server: CouchDB (Erlang/OTP)
Set-Cookie: AuthSession=cm9vdDo1MEJCRkYwMjq0LO0ylOIwShrgt8y-UkhI-c6BGw; Version=1; Path=/;
HttpOnly
{"ok":true,"name":"root","roles":["_admin"]} // <-- i expect that
And no cookie set.
I also tried curl, it works :
> curl http://localhost:5984/_session
{"ok":true,"userCtx":{"name":null,"roles":[]},"info":{"authentication_handlers":
["cookie","default"]}}
> curl -X POST http://localhost:5984/_session -H "Content-Type: application/json" -d '{"name":"my_username","password":"my_password"}'
{"ok":true,"name":"my_username","roles":["_admin"]}
But I need it to work in a react app, from http:localhost:3000
Maybe it's CORS related? I enabled CORS in CouchDB settings.
How can i modify the first request in order to get the user object for the name/password supplied?
I think Authentication Set-Cookie produce by backend server not by front end. So you need backend like Node.js to get cookie and then get it again from your front end.
Following this tutorial -> https://developer.vimeo.com/api/upload/thumbnails
I have setup a time of 180s and the request of step 2 has returned status 201.
all the links have a similar format:
https://i.vimeocdn.com/video/<id>_<size>.jpg?r=pad'
Here is the request:
{ protocol: 'https:',
host: 'i.vimeocdn.com',
port: 443,
method: 'PUT',
headers:
{ 'Content-Type': 'image/jpg',
Accept: 'application/vnd.vimeo.*+json;version=3.4',
'User-Agent': 'Vimeo.js/2.1.1',
Authorization: 'Bearer 9a3918a750089766b46f0e8a59a79f49',
'Content-Length': 189 },
body:
'_readableState=&readable=true&_events=&_eventsCount=1&_maxListeners=&path=%2Ffile.jpg&fd=&flags=r&mode=438&start=&end=&autoClose=true&pos=&bytesRead=0&closed=false',
path: '/video/<id>_1920x1080.jpg' }
}
I've tried with that URI but allways get this result:
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>
{ connection: 'close',
'cache-control': 'no-cache',
'content-type': 'text/html',
'accept-ranges': 'bytes, bytes',
via: '1.1 varnish, 1.1 varnish',
'access-control-allow-origin': '*',
date: 'Wed, 10 Jun 2020 16:59:05 GMT',
'x-served-by': 'cache-dfw18638-DFW, cache-ewr18125-EWR',
'x-cache': 'MISS, MISS',
'x-cache-hits': '0, 0',
'x-timer': 'S1591808345.129097,VS0,VE49',
'transfer-encoding': 'chunked' }
The token has the following access:
private create edit upload video_files public
I've tried to do the PUT request to the api hostname, but the page couldn't be found.
Any ideas?
Thanks in advance.
I've used the wrong link, the PUT request must be to a link that looks like this:
https://i.cloud.vimeo.com/video/<id>?expires=<timestamp>&sig=<hash>
I am using react-native 0.50.3 to send token authenticated requests to my backend and unfortunately the 'authorization' part of the header is not send by the fetch.
My code is the following :
async componentDidMount() {
var mytoken = await AsyncStorage.getItem('token');
fetch('http://myserver:8000/home', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Origin': '',
'Content-Type': 'application/json',
'authorization': 'Bearer ' + mytoken
}
})
.then((response) => response.json())
.then((content) => {
this.state.user = content.user;
})
.done();
}
And on my server side, the wireshark trace shows that the authorization is not in the request header :
Hypertext Transfer Protocol
GET /home/ HTTP/1.1\r\n
Host: 10.150.21.124:8000\r\n
Content-Type: application/json\r\n
Origin: \r\n
Accept: application/json\r\n
User-Agent: Expo/2.3.0.1012011 CFNetwork/893.14 Darwin/17.3.0\r\n
Accept-Language: en-us\r\n
Accept-Encoding: gzip, deflate\r\n
Connection: keep-alive\r\n
\r\n
[Full request URI: http://10.150.21.124:8000/home/]
[HTTP request 1/1]
[Response in frame: 2326]
And of course I get a 401 unhautorized by the server.
My backend is a django API with CORS installed and CORS_ORIGIN_ALLOW_ALL = True and ALLOWED_HOSTS = ['*'].
The versions of my developments framework elements are the following :
npm 4.6.1
node v9.3.0
react-native-cli 2.0.1
One important update, the request I try to do with react-native works like a charm with postman. So the issue is not located on the server side.
Thank you for your help.
Alex.
try with trailing slash, in url address:
fetch('http://myserver:8000/home/', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Origin': '',
'Content-Type': 'application/json',
'authorization': 'Bearer ' + mytoken
}
})
.then((response) => response.json())
.then((content) => {
this.state.user = content.user;
})
.done();
Pooya's answer worked for me by adding the trailing slash on the request object. Strange because it worked on postman without the trailing slash hence the challenge in debugging. P.S i am also using the same stack, django, django REST framework (DRF) react native
fetch('http://mywebsite.com/posts/', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token
}
})
I'm having a problem with FineUploader 4.4 in Firefox. As you know, Firefox sends the following HTTP accept header by default:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
But since AmazonS3 returns JSON data after I upload a file via POST with FineUploader, I need to override FineUploader to send an application/json Accept header:
$('#demoUploader').fineUploaderS3({
autoUpload: true,
request: {
endpoint: "https://s3.amazonaws.com/myapp",
accessKey: "AKIAJ4VQLGW68A2Y6JLQ",
customHeaders: { 'Accept': 'application/json' }
},
... etc
But this is not working. FineUploaderS3 ignores my customHeader option and still sends the default Accept header. What am I doing wrong?
Solved! Thanks #RayNicholus
I had to add the customHeaders option to my uploadSuccess endpoint in order to force Firefox to send the application/json Accept header.
uploadSuccess: {
endpoint: "/api/amazons3/uploadSuccessful",
customHeaders: { 'accept': 'application/json' }
},