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"
});
Related
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.
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 feel like a newbie here but I'm trying to run a simple AJAX request from a browser to access a GCF and Chrome is reporting:
XMLHttpRequest cannot load
https://us-central1-bustling-opus-830.cloudfunctions.net/Authenticate.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'https://beast.reachboarding.com.au' is therefore not
allowed access.
I've got a function called Authenticate (as shown above) that's using a bucket called:
bustling-opus-830.appspot.com
I've used gsutil to set CORS using the following JSON file:
[{
"origin": ["https://beast.localdev.com.au","*"],
"responseHeader": ["Content-Type"],
"method": ["GET", "HEAD", "DELETE", "OPTIONS"],
"maxAgeSeconds": 3600
}]
With the following command:
gsutil cors set cors.json gs://bustling-opus-830.appspot.com/
And then get the following output from the corresponding get command:
gsutil cors get gs://bustling-opus-830.appspot.com/
[{"maxAgeSeconds": 3600, "method": ["GET", "HEAD", "DELETE", "OPTIONS"], "origin": ["https://beast.localdev.com.au", "*"], "responseHeader": ["Content-Type"]}]
I'm using the default example code that's provided when you create a new function as stated below:
/**
* Responds to any HTTP request that can provide a "message" field in the body.
*
* #param {!Object} req Cloud Function request context.
* #param {!Object} res Cloud Function response context.
*/
exports.helloWorld = function helloWorld(req, res) {
// Example input: {"message": "Hello!"}
if (req.body.message === undefined) {
// This is an error case, as "message" is required.
res.status(200).send('No message defined!');
} else {
// Everything is okay.
console.log(req.body.message);
res.status(200).send(req.body.message);
}
};
And a simple HTML with the following Javascript:
$.ajax({
url: "https://us-central1-bustling-opus-830.cloudfunctions.net/Authenticate",
type: "POST",
data: {
message: 'Testing'
},
dataType: 'json',
success: function (response) {
console.log(response);
},
error: function (xhr, status) {
console.log(xhr);
}
});
Which is causing the error.
In my DEV console I can see the network request go through. Here are the HTTP Response Headers I'm getting are:
cache-control:private
content-encoding:gzip
content-length:27
content-type:text/html; charset=utf-8
date:Wed, 08 Feb 2017 03:45:50 GMT
etag:W/"7-274e639a"
function-execution-id:azc1zqfb1tq8
server:Google Frontend
status:200
vary:Accept-Encoding
x-cloud-trace-context:70e08d634a9644c32530326de0471a64;o=1
x-cloud-trace-context:70e08d634a9644c32530326de0471a64
x-powered-by:Express
I would have expected to see the Access-Control-Allow-Origin header within the Response Headers to indicate that it was allowing * but I'm definitely not seeing it.
The crazy thing though is that when I look at the Network item and click on Response I get:
Testing
Which suggests that all things being equal, it ACTUALLY ran!
I apologise if this has been answered before but I've searched for as many different keywords and nothing seems to have solved my problem. I thought a fresh pair of eyes on the issue (and some decent expertise) would help.
Thanks in advance!
Your foreground (HTTP) Google Cloud Function needs to set the appropriate CORS headers in the responses to the AJAX client requests. The request and response parameters of HTTP Functions have equivalent properties to the corresponding ExpressJS objects which can be used to set the CORS headers and respond to preflight requests as needed.
For example:
exports.Authenticate = function Authenticate (req, res) {
//set JSON content type and CORS headers for the response
res.header('Content-Type','application/json');
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type');
//respond to CORS preflight requests
if (req.method == 'OPTIONS') {
res.status(204).send('');
}
//continue function ...
};
The headers and logic above should be modified to reflect the particular needs of your service but should hopefully help you get started.
You can also use the cors package to fix this, as recommended by Google. In fact, they also use this in their own sample codes. Check this example.
This is the code -
const cors = require('cors')({
origin: true,
});
//Your code here
//Use the following function instead of just res.send. return keyword is not compulsory here
return cors(req, res, () => {
res.send();
});
If you are still interested in an answer, I actually wrote a blog post on how to handle that with Express middleware: https://mhaligowski.github.io/blog/2017/03/10/cors-in-cloud-functions.html.
I'm trying to consume my (CORS compatible) RESTful service
#Path("/greeting")
#GET
#Produces("application/json")
public Response greeting() {
String result = "{\"id\":1,\"content\":\"Hello, World!\"}";
return Response.ok() //200
.entity(result)
.header("Access-Control-Allow-Origin", "*")
.build();
}
from my AngularJS application.
function ($scope, $http) {
$scope.dashboard = "ESCO Dashboard";
console.log('start');
// Simple GET request example:
$http({
method: 'GET',
url: 'http://localhost:8080/NobelGrid/api/users/greeting'
}).then(function successCallback(response) {
console.log('success');
$scope.greeting = response.data;
}, function errorCallback(response) {
console.log('error');
});
console.log('end');
}
but I have this error:
XMLHttpRequest cannot load http://localhost:8080/NobelGrid/api/users/greeting. 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:63342' is therefore not allowed access.
Using Console Network of Chrome this seems true cause the Response Header is:
Anyway accessing to the REST service from the browser and not from the Angular app, the header is correct
I also tried this tutorial:
https://spring.io/guides/gs/consuming-rest-angularjs/
with their RESTful service (also CORS compatible, they said), but the result is the same.
ps: I'm using WebStorm as IDE.
UPDATE - SOLVED
Writing this handler at server-side:
#Path("/greeting")
#OPTIONS
#Produces("application/json")
public Response greetingOPT() {
return Response.status(200) //200
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, X-Codingpedia,Authorization")
.build();
}
it works. At the beginning it gives to me another error:
Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight [..]
but adding Authorization to the Access-Control-Allow-Headers of the GET and POST resolve the problem.
Look at the error message:
Response to preflight request
Look at the Network log:
Request Method: OPTIONS
Look at your API:
#GET
You need to write a handler for the preflight OPTIONS request before the browser will make the GET request to the handler you have written.
In my Angular app below is the error I'm getting when I try to login while developing locally (Chrome):
XMLHttpRequest cannot load https://www.tickertags.com/app/api/login.
Response to preflight request doesn't pass access control check:
The 'Access-Control-Allow-Origin' header has a value 'http://localhost:8100'
that is not equal to the supplied origin.
Origin 'http://localhost' is therefore not allowed access.
The login function from my loginController
function login(credentials) {
console.log('credentials',credentials);
AuthFactory.login(credentials).then(function (user) {
$rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
$scope.setCurrentUser(user);
if (user.password_reset) {
$location.path('/password');
} else {
$location.path('/tickers');
}
}, function () {
console.log('"Invalid Username/Password"');
$scope.loginData.message = "Invalid Username/Password";
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
}, function () {
console.log('"Invalid Username/Password"');
$scope.loginData.message = "Invalid Username/Password";
$rootScope.$broadcast(AUTH_EVENTS.loginFailed);
});
}
The AuthFactory.login function hits an API that is hosted on production. I'm not sure what I'm missing? This is what my localhost link looks like http://localhost/static/manage/v2/#/login
Hope this helps someone else who is running into this problem, and can't access anything on the server side.
I figured out my problem, I was trying to hit an absolute path with my API call to login ie: www.tickertags.com/api/... instead of just /api/... that fixed it.
To surpass CORS problem, you have to configure both front-end and back-end.
For front-end, when you call the myApp.run() method on the initialization you can configure default HTTP headers:
$http.defaults.useXDomain = true;
delete $http.defaults.headers.common['X-Requested-With'];
For the back-end part you'll need to modify request headers. I don't know what's on your back-end, but I usually use these on my local Node server.
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
});