I'm trying to make a GET request to a GCP Cloud Function from the frontend in JS, but I am getting the error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://us-central1-<project>.cloudfunctions.net/<function-name>. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
I was originally going to call a 3rd party API from the front end but it gave me this error too, then I was going to see if I could use a CF as a middleman, but I'm guessing I'll need to set up a server?
Surely its possible to make a GET request from the frontend to a cloud function or other site?
axios({
method: 'GET', //you can set what request you want to be
url: "http://<cloud-function>.com/<function-name>",
data: {message: "test"},
}).then(data => {
console.log(data)
}).catch(error => {
console.log(error)
})
This is browser security policy to avoid unexpected request. If you is owner of function, you need to setup a whitelist for your server.
exports.corsEnabledFunction = (req, res) => {
// Set CORS headers for preflight requests
// Allows GETs from any origin with the Content-Type header
// and caches preflight response for 3600s
res.set('Access-Control-Allow-Origin', '*');
if (req.method === 'OPTIONS') {
// Send response to OPTIONS requests
res.set('Access-Control-Allow-Methods', 'GET');
res.set('Access-Control-Allow-Headers', 'Content-Type');
res.set('Access-Control-Max-Age', '3600');
res.status(204).send('');
} else {
res.send('Hello World!');
}
};
This code is following GCP official document https://cloud.google.com/functions/docs/writing/http
It's possible definitely. You need to allow your origin in your cloud function.
On the other hand, please try to use the below:
axios({
method: 'GET', //you can set what request you want to be
url: "https://cors-anywhere.herokuapp.com/http://<cloud-function>.com/<function-name>",
data: {message: "test"},
}).then(data => {
console.log(data)
}).catch(error => {
console.log(error)
})
As mentioned by others, I can allow CORS within the cloud function, but here is how to do so usng Nodejs:
exports.someFunction = (req, res) => {
res.set('Access-Control-Allow-Origin', "*")
res.set('Access-Control-Allow-Methods', 'GET, POST')
res.set('Access-Control-Allow-Headers', 'Content-Type');
let message = req.query.message || req.body.message || 'Hello World!';
res.status(200).send(message);
};
Now I can call this from my frontend.
Related
This question already has answers here:
Why doesn't adding CORS headers to an OPTIONS route allow browsers to access my API?
(36 answers)
Closed 7 months ago.
i got these two CORS error (that is normally easy to fix) when i make a POST request (with a body preciselly), the other requests all works well.
I checked the content of my this.state.filter it's always in a good format. I also tested the route with Postman, with the same body that my front put in the request and it works good.
Even if the body is empty but present i got the errors, but if i don't put any second argument on the axios post method call and readapt my back to not use the req.body, it will works (the response will just not be what i really want).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3001/cat/filterlist. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 200.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3001/cat/filterlist. (Reason: CORS request did not succeed). Status code: (null)
My back-end in node.js with express (The Access-Control-Allow-Origin header is there):
router.post("/filterlist", function (req, res, next) {
func.getFilteredList(req.body, (result) => {
res.header("Access-Control-Allow-Origin", "*");
res.send(result);
});
});
And my front-end in react with axios to make the request :
applyFilter = () => {
console.log(this.state.filter);
axios
.post("http://localhost:3001/cat/filterlist", this.state.filter)
.then((data) => {
console.log(data.data);
// this.setState({ cats: data.data });
})
.catch((error) => {
console.log(error);
});
}
This case without the second argument (the body) in the axios method call and a empty array to replace the request body req.body, will works but the function no longer makes sense -_- :
router.post("/filterlist", function (req, res, next) {
func.getFilteredList([], (result) => {
res.header("Access-Control-Allow-Origin", "*");
res.send(result);
});
});
applyFilter = () => {
console.log(this.state.filter);
axios
.post("http://localhost:3001/cat/filterlist")
.then((data) => {
console.log(data.data);
// this.setState({ cats: data.data });
})
.catch((error) => {
console.log(error);
});
}
I will be very thankful if someone can solve my issue ;(.
install cors: $ npm install cors
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
this will enable CORS for all requests on your server.
I hope this hepled!
I am trying to access linkedin profile using axios get request, which doesn't work on localhost and I get the following error
XMLHttpRequest cannot load
https://api.linkedin.com/v1/people/~:(id,email-address)?format=json.
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:8030' is therefore not allowed
access. The response had HTTP status code 401.
I am able to get access-token using react-linkedin-login package, after getting the access token I am trying the following code
var linkedInUrl = `https://api.linkedin.com/v1/people/~:(id,email-address)?format=json`;
var headers = {
'Authorization': `Bearer ${accessToken}`,
'Access-Control-Allow-Methods':'GET,PUT,PATCH,POST,DELETE',
'Access-Control-Allow-Origin':'*',
'Access-Control-Request-Headers':'Origin, X-Requested-With, Content-Type, Accept',
'Content-Type':'application/x-www-form-urlencoded'
};
return (dispatch) => {
axios.get(linkedInUrl, {headers}).then(({data}) => {
console.log(data);
}, (error) => {
console.log(error);
});
}
The problems lies in linkedin server how it takes request I guess, it doesn't allow localhost to make call I think. How to overcome this to actually develop the service before I deploy and run on server.
Thanks for helping..
This is because of a browser restriction called the "Same-origin Policy", which prevents fetching data from, or posting data to, URLs that are part of other domains. You can get around it if the other domain supports Cross-origin Resource Sharing (CORS), but it looks like LinkedIn doesn't, so you may have trouble.
One way around this is to have a web service which can proxy your request to LinkedIn - there's no domain restrictions there.
https://en.wikipedia.org/wiki/Same-origin_policy
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
try jsonp for CORS request - reference - axios cookbook
var jsonp = require('jsonp');
jsonp(linkedInUrl, null, function (err, data) {
if (err) {
console.error(err.message);
} else {
console.log(data);
}
});
EDIT
Use jQuery to perform JSONP request and to set headers
$.ajax({url: linkedInUrl,
type: 'GET',
contentType: "application/json",
headers: header, /* pass your header object */
dataType: 'jsonp',
success: function(data) {
console.log(data);
},
error: function(err) {
console.log('Error', err);
},
});
https://cors-anywhere.herokuapp.com/ - Add this before the url and it will work
I am using Laravel Lumen to create an API for my MeteorJS App. This is my code inm y meteorJS on imports\api\tasks.js
...
import { HTTP } from 'meteor/http';
import { WebApp } from 'meteor/webapp';
if (Meteor.is_client) {
// Calling our Meteor server's function
// and simply storing data into current session
Meteor.call('fetchDataFromUrl', function (error, response) {
Session.set('external_server_data', response)
});
// Providing meteor data for template (it renders on data received)
Template.data.server_data = function () {
return Session.get('external_server_data');
};
}
if (Meteor.is_server) {
Meteor.methods({
// Declaring a method
retrieve_doc_types: function () {
this.unblock();
return Meteor.http.get(api_url);
}
});
}
Meteor.methods({
'tasks.insert'(make, model, year) {
check(make, String);
check(model, String);
check(year, String);
if (! Meteor.userId()) {
throw new Meteor.Error('not-authorized');
}
HTTP.call("POST", "http://localhost:8000/api/v1/car",
{data: {"make":make, "model":model, "year":year}},
function (error, result) {
if (!error) {
console.log(result);
} else{
console.log("http post error");
};
});
},
....
but when I got this error:
XMLHttpRequest cannot load http://localhost:8000/api/v1/car. 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:3000' is therefore not allowed access. The response had HTTP status code 405.
tasks.js:81 http post error
do anyone have an idea? I am new with MeteorJS
try this in your server/main.js
WebApp.rawConnectHandlers.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
return next();
});
Where do you call the Method? The method is called tasks.insert but the code you provide only calls fetchDataFromUrl method.
Here are some ideas.
Check your call on the client is used asynchronously. From the Metor HTTP doc: On the client, this function must be used asynchronously by passing a callback. Note that some browsers first send an OPTIONS request before sending your request (in order to determine CORS headers).
I had CORS problem too in one of my project and I ended up by using HTTP library server side only. You can do it by surrounding your HTTP call with a Meteor.isServer.
Somebody tried to answer But I am not getting it. You try your luck.
https://codexample.org/questions/9358/no-access-control-allow-origin-error-in-meteor-app.c
Try package - simple:json-routes and put following code at serverside startup.
// Enable cross origin requests for all endpoints
JsonRoutes.setResponseHeaders({
"Cache-Control": "no-store",
"Pragma": "no-cache",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, PUT, POST, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With"
});
I have a golang HTTP server with code like:
http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
log.Println("New incoming request")
// Authenticate
if u, p, ok := r.BasicAuth(); ok {
log.Println("Success")
return
}
log.Println("Failed")
I call this HTTP endpoint from a JS frontend, a react app deployed on port 3000, using code:
fetch('http://localhost:8080/login', {
method: 'post',
headers: {
'Authorization': 'Basic ' + btoa(authHeader),
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*'
},
body: 'A=1&B=2'
})
.then(function (response) {
console.log("Authentication Success")
})
.catch(function (err) {
console.log("Authentication fail", err)
});
The above code fails with the following logs.
On the server side:
New incoming request
Failed
On the browser, in the developer tools logs:
Fetch API cannot load http://localhost:8080/login. 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:3000' is therefore not allowed access. The response had HTTP status code 401. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Can someone help fix the authentication problem ? I am not sure if I am missing something related to CORS on the server side or doing bad authentication on the client side. Any help ? Thanks.
The Access-Control-Allow-Origin: * has to be sent from the server, not by the client. Assuming you are in a standard net/http handler function, try this code:
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
if (r.Method == "OPTIONS") {
w.Header().Set("Access-Control-Allow-Headers", "Authorization") // You can add more headers here if needed
} else {
// Your code goes here
}
}
First - you need to use schema in your handler:
w.Header().Set("Access-Control-Allow-Origin", "*")
if (r.Method == "OPTIONS") {
w.Header().Set("Access-Control-Allow-Headers", "Authorization") // You can add more headers here if needed
} else {
// Your code goes here
}
But before it you need to specify in main "OPTIONS":
router.HandleFunc("/your_route/", your_method).Methods("POST", "OPTIONS")
It's because your browser doing 2 request - first to check ability to use some headers (Authorization for example) and next step is posting data
Here is my code snippet:
const url = util.API + '/ip/ip2addr' + `?ip=${this.state.ip}&key=${util.appKey}`;
fetch(url, {mode: 'no-cors'}).then(res => res.json()).then(data => {
//does not call this callback
this.setState({res: data.result});
}).catch(err => {
});
I saw the response, but not call the promise.then method, why? how can I get the response data?
It seems third-party api do not support CORS, so, my think is to write a node server.
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded(extended: true));
app.get('/ip/ip2addr', (req, res) => {
const url = util.API + '/ip/ip2addr' + `?ip=${ip}&key=${appKey}`;
request
.get({url}, (err, response, body) => {
if (!err && response.statusCode == 200) {
res.json(body);
}
})
});
app.listen(port, err => {
if(err) throw err;
console.log(`Server is listen on port ${port}`);
});
After search and read some articles, I think webpack-dev-server proxy settings will solve this problem too.
MDN has an explanation why your code doesn't work:
no-cors — Prevents the method from being anything other than HEAD, GET or POST. If any ServiceWorkers intercept these requests, they may not add or override any headers except for these. In addition, JavaScript may not access any properties of the resulting Response. This ensures that ServiceWorkers do not affect the semantics of the Web and prevents security and privacy issues arising from leaking data across domains.
Basically, you a no-cors request results in an opaque response, that which JavaScript code cannot read. You're allowed to make the request, but you still can't circument CORS.
While you can't read from these responses, one use case for no-cors is service workers, which may intercept want to intercept requests from different origins (for instance, when an <img /> loads), e.g., for caching. (Jake Archibald explains a bit about this here)