Having an issue with a firebase function that I need to work with cors. Based off the documentation and all the posts I've read it should be working but seem's like no matter what I try I keep getting the same error:
Failed to load <URL>: 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 500.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
And here is the corresponding code in my firebase functions index.js file:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const cors = require('cors')({origin: true});
const stripe = require('stripe')('<TEST_KEY>');
const gcs = require('#google-cloud/storage')({keyFilename: '<PATH_TO_KEY>'});
const Easypost = require('#easypost/api');
const api = new Easypost('<TEST_KEY>');
admin.initializeApp(functions.config().firebase);
exports.processOrder = functions.https.onRequest((req, res) => {
cors(req, res, () => {
var body = JSON.parse(req.body);
if (
!body.shipment_id ||
!body.items ||
!body.card
) return res.set('Access-Control-Allow-Origin', '*').send({error: true, message: 'Missing information'});
getPrices(body.items, (err, prices, totalPrice) => {
if (err) return res.set('Access-Control-Allow-Origin', '*').send({error: err, message: "Error"})
// Create a new customer and then a new charge for that customer:
stripe.customers.create({
email: 'test#example.com'
}).then((customer) => {
return stripe.customers.createSource(customer.id, {
source: body.card.token.id
});
}).then((source) => {
return stripe.charges.create({
amount: (totalPrice * 100),
currency: 'usd',
customer: source.customer
});
}).then((charge) => {
return res.set('Access-Control-Allow-Origin', '*').send({error: false, message: "Success"});
}).catch((err) => {
console.log(err);
return res.set('Access-Control-Allow-Origin', '*').send({error: err, message: "Error"});
});
});
});
});
Any help would be greatly appreciated :)
Edit: Just wanted to note: I've tried only setting res.set('Access-Control-Allow-Origin', '*') and not using the cors middleware, and I've tried not setting the header and only using cors. Neither of which worked :(
Solution: As #sideshowbarker said in a comment, my function had an error elsewhere before returning. The Access-Control-Allow-Origin was never even getting set. Once I fixed the error it was all good! Ty!
In node you can use a package to solve this problem. To enable all CORS install the following package:
npm install cors
Then assuming you are using express you can then enable CORS by the following lines of code:
var cors = require('cors');
app.use(cors());
Related
I have the following code:
const { v4: uuidv4 } = require('uuid')
const functions = require('firebase-functions')
const nodemailer = require('nodemailer')
const cors = require('cors')({ origin: true })
const gmailEmail = functions.config().gmail.email
const gmailPassword = functions.config().gmail.password
const mailto = functions.config().gmail.mailto
const mailTransport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: gmailEmail,
pass: gmailPassword
}
})
exports.sendMail = functions.https.onRequest((req, res) => {
cors(req, res, () => {
const items = req.body.items.forEach(item => (
`${item.quantity} x ${item.uuid} (${item.name})\n`
))
if (req.method === 'POST') {
const mailOptions = {
from: gmailEmail,
replyTo: gmailEmail,
to: mailto,
subject: `Order ${uuidv4()} from ${req.body.name} (${req.body.email})`,
text: `Order\n\n${items}`
}
mailTransport.sendMail(mailOptions)
res.status(200).send(JSON.stringify({ status: 'OK' }))
} else {
res.status(400).send(JSON.stringify({ status: 'method not allowed' }))
}
})
})
For some reason it worked once and then keeps giving me
Access to fetch at 'https://xxxxx.cloudfunctions.net/sendMail' from origin 'https://xxxx.com' 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.
What am I missing? If possible I'd like to avoid using Express.
For you to configure CORS on your Cloud Functions with Firebase, you will need to configure and set some additional parameters - as mentioned in the official documentation here - for CORS to be authorized and execute via HTTP in your application.
The parameters in an example of settings that you will need to configure on your application is the following:
const express = require('express');
const cors = require('cors')({origin: true});
const app = express();
app.use(cors({ origin: true }));
I would recommend you to give it a try using the above setting for you to give the authorization in your backend.
Besides that, the below questions from the Community, there are some other solutions and use cases of similar issues to yours, that I believe should help you achieve the configuration and that I think you should check as well.
Enabling CORS in Cloud Functions for Firebase
Enable CORS while an XMLHttpRequest error occurs in flutter web
Let me know if the information helped you!
I have CORS installed for firebase cloud functions.
I'm using sendgrid to send a transactional email.
I was using this EXACT code in another folder and this function was returning no problem - but I merged 2 separate documents of functions into one and now I keep getting the error...
Access to XMLHttpRequest at 'cloud function trigger' from origin 'my website' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Really confused as to what it could be...
const cors = require('cors')({ origin: true });
exports.sendRequest = functions.https.onRequest((req, res) => {
cors(req, res, () => {
return Promise.resolve()
.then(() => {
if (req.method !== 'POST') {
const error = new Error('Only POST requests are accepted');
error.code = 405;
throw error;
}
const msg = {
to: req.body.companyEmail,
from: req.body.name,
text: 'and easy to do anywhere, even with Node.js',
html: '<strong>and easy to do anywhere, even with Node.js</strong>'
}
};
return sgMail.send(msg);
})
.then((response) => {
if (response.body) {
res.send(response.body);
} else {
res.end();
}
})
.catch((err) => {
console.error(err);
return Promise.reject(err);
});
})
})
I wrote and deployed a Firebase Cloud function with CORS support:
const cors = require('cors')({
origin: true
});
...
exports.test = functions.https.onRequest((req, res) => {
cors(req, res, () => {
const idToken = req.query.idToken;
admin.auth().verifyIdToken(idToken)
.then((decoded) => {
var uid = decoded.uid;
return res.status(200).send(uid);
})
.catch((err) => res.status(401).send(err));
});
});
I call the HTTP Trigger from my React app using the Axios package:
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
// Send token to your backend via HTTPS
// ...
console.log(idToken);
axios.get('https://XXX.cloudfunctions.net/test?idToken='+idToken)
.then(response => console.log(response));
}).catch(function(error) {
// Handle error
});
Unfortunately, when running the app on my local server, I still get an error:
Failed to load...Redirect From..to..
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
PS. I have used the procedure reported here
I found an answer here
exports.test = functions.https.onRequest((req, res) => {
cors(req, res, () => {});
const idToken = req.query.idToken;
admin.auth().verifyIdToken(idToken)
.then((decoded) => {
var uid = decoded.uid;
return res.status(200).send(uid);
})
.catch((err) => res.status(403).send(err));
});
I am a bit stuck with getting a response from the meetup API. The error I am getting:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
Here's my code:
var config = {'Access-Control-Allow-Headers': 'Authorization'}
axios.get(`https://api.meetup.com/self/calendar?&sign=true&photo-host=public&page=20`, {headers: config})
.then(response => {
console.log(response.data)
this.posts = response.data
})
.catch(e => {
this.errors.push(e)
})
I've read a little bit on CORS here Cross-Origin Resource Sharing (CORS) but all my attempts in getting this to work have failed.
Can any of you shed some light on this?
Thanks,
Manu
your api is not served on same host. either use reverse proxy like nginx or use cors toggle extension.
Right, I got this working now. Both #FailedUnitTest and #Manav Mandal suggestions are worth considering. However, instead of using OAuth you can use an API key - which I found easier. Also, my proxy is my expressJS server.
On the server side you would have something along the following lines:
var express = require('express');
var axios = require('axios');
// meetup API
var instance = axios.create({
baseURL: 'https://api.meetup.com/'
});
app.get('/anything', function(req, res) {
const apiKey = 'yourKey';
const isSigned = 'true';
const photoHost = 'public';
const pageCount = '20';
const url = '/self/calendar?' + 'key=' + apiKey + '&sign=' + isSigned
+ '&photo-host=' + photoHost + '&page=' + pageCount + '';
instance.get(url)
.then(response => {
return res.send(response.data);
})
.catch(e => {
return e;
})
});
And the client side:
data () {
return {
cards: [],
errors: []
};
},
created () {
axios.get('/anything')
.then(response => {
this.cards = response.data;
})
.catch(e => {
this.errors.push(e);
});
}
Make sure both your server and your client run over the same port.
Regards,
Manu
I'm building a React application and I'm trying to make a call to https://itunes.apple.com/search?term=jack+johnson
I have a helper called requestHelper.js which looks like :
import 'whatwg-fetch';
function parseJSON(response) {
return response.json();
}
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
error.response = response;
throw error;
}
export default function request(url, options) {
return fetch(url, options)
.then(checkStatus)
.then(parseJSON);
}
So I get:
XMLHttpRequest cannot load
https://itunes.apple.com/search?term=jack%20johnson. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access.
My express server looks like this:
const ip = require('ip');
const cors = require('cors');
const path = require('path');
const express = require('express');
const port = process.env.PORT || 3000;
const resolve = require('path').resolve;
const app = express();
app.use(cors());
app.use('/', express.static(resolve(process.cwd(), 'dist')));
app.get('*', function(req, res) {
res.sendFile(path.resolve(resolve(process.cwd(), 'dist'), 'index.html'))
});
// Start app
app.listen(port, (err) => {
if (err) {
console.error(err.message);
return false;
}
const divider = '\n-----------------------------------';
console.log('Server started ✓');
console.log(`Access URLs:${divider}\n
Localhost: http://localhost:${port}
LAN: http://${ip.address()}:${port}
${divider}
`);
});
I have tried using mode: 'no-cors' but is not actually what I need since the response is empty.
Am I doing something wrong with this configuration?
The same origin policy kicks in when code hosted on A makes a request to B.
In this case A is your Express app and B is iTunes.
CORS is used to allow B to grant permission to the code on A to read the response.
You are setting up CORS on A. This does nothing useful since your site cannot grant your client side code permission to read data from a different site.
You need to set it up on B. Since you (presumably) do not work for Apple, you can't do this. Only Apple can grant your client side code permission to read data from its servers.
Read the data with server side code instead.