Meteor.http.call gives not allowed by Access-Control-Allow-Origin - meteor

When I try to call an external server for JSON queries in Meteor with the Meteor.http.call("GET") method I get the error message "not allowed by Access-Control-Allow-Origin".
How do I allow my meteor app to make HTTP calls to other servers?
Right now I run it on localhost.
The code I run is this:
Meteor.http.call("GET",
"http://api.vasttrafik.se/bin/rest.exe/v1/location.name?authKey=XXXX&format=json&jsonpCallback=processJSON&input=kungsportsplatsen",
function(error, result) {
console.log("test");
}
);

There are other questions similar to this on StackOverflow.
You're restricted by the server you're trying to connect to when you do this from the client side (AJAX).
One way to solve it is if you have access to the external server, you can modify the header file to allow some, or all origins by:
Access-Control-Allow-Origin: *
However, if you place the call on the server side and not provide a callback function, the call will be made synchronously, thus not with AJAX, and it should succeed.
Here's
Meteor.methods({checkTwitter: function (userId) {
this.unblock();
var result = Meteor.http.call("GET", "http://api.twitter.com/xyz", {params: {user: userId}});
if (result.statusCode === 200) return true
return false;
}});

Related

Firebase email verification from server side

I have a link to default email verification function in Firebase.
Using this link from the browser works fine, however it fails when being used from server side with the following code:
try {
const url = `https://example.com/__/auth/action?mode=verifyEmail&oobCode=${oobCode}&apiKey=${apiKey}&lang=en`;
const response = await axios.get(url);
if (response.data.success) {
return next();
} else {
return next(new ErrorResponse("Failed email verification", FORBIDDEN));
}
} catch (error) {
return sendFailedWithErr(res, error.message);
}
When I am copying the URL used in the server side the exact same URL works from the browser, but fails on the server side.
Would appreciate any idea what is the problem.
This is because a call to this URL is not going to return a response that you can check like the response of a REST API endpoint with, e.g. response.data.success.
As you will see here, this URL is supposed to be used to open a web page in which you will:
Get the values passed as QueryString parameters (e.g. mode or oobCode)
Call, from the web page some methods of the Firebase JavaScript SDK, like applyActionCode() in the case of email verification.
You may be able to mimic this action from a server, but I've never tried.

Unhandled Rejection (SyntaxError): Unexpected token < in JSON at position 0?

I am trying to fetch local api made in asp.net api which is running in https://localhost:44388/. When I tried to fetch get request it responds ok but return html not json. The problem might occur by two reasons:
1.typo in url (But I checked in my browser, it worked)
2.Server restart needed
What might be the problem with my code?
componentDidMount(){
var proxyUrl = "http://127.0.0.1:3000/";
var targetUrl = "https://127.0.0.1:44388/api/product/getproducts";
fetch(proxyUrl+targetUrl, {
method:'GET',
headers:{
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Mehods': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Credentials':'*',
'Content-type':'application/json'
}
})
.then(data=>{
if(!data.ok){
throw new Error("Error");
}else{
return data.json();
}
})
.then(data=>this.setState({products:data}))
}
when you give parameter as:proxyUrl+targetUrl,
actually the url which you have called is :
http://127.0.0.1:3000/https://127.0.0.1:44388/api/product/getproducts
which does not seems to be correct.
i think the structure of url you'v given to fetch function is wrong.

Insert new collection after function runs on server

When I return the geocode from googles API I'm trying to save it into my database. I've been trying to use the code below, to just insert a Test document with no luck. I think it has something to do with meteor being asynchronous. If I run the insert function before the googleMapsClient.geocode function it works fine. Can someone show me what I'm doing wrong.
Meteor.methods({
'myTestFunction'() {
googleMapsClient.geocode({
address: 'test address'
}, function(err, response) {
if (!err) {
Test.insert({test: 'test name'});
}
});
}
});
I see now where you got the idea to run the NPM library on the client side, but this is not what you really want here. You should be getting some errors on the server side of your meteor instance when you run the initial piece of code you gave us here. The problem is that the google npm library runs in it's own thread, this prevents us from using Meteor's methods. The easiest thing you could do is wrap the function with Meteor.wrapAsync so it would look something like this.
try {
var wrappedGeocode = Meteor.wrapAsync(googleMapsClient.geocode);
var results = wrappedGeocode({ address : "testAddress" });
console.log("results ", results);
Test.insert({ test : results });
} catch (err) {
throw new Meteor.Error('error code', 'error message');
}
You can find more info by looking at this thread, there are others dealing with the same issue as well
You should run the googleMapsClient.geocode() function on the client side, and the Test.insert() function on the server side (via a method). Try this:
Server side
Meteor.methods({
'insertIntoTest'(json) {
Test.insert({results: json.results});
}
});
Client side
googleMapsClient.geocode({
address: 'test address'
}, function(err, response) {
if (!err) {
Meteor.call('insertIntoTest', response.json);
}
});
Meteor Methods should be available on the both the server and client sides. Therefore make sure that your method is accessible by server; via proper importing on /server/main.js or proper folder structuring.
(If a method contains a secret logic run on the server, it should be isolated from the method runs on both server & client, though)

Writing an async test with Intern

I am trying to write an Integration test which calls my real service (that returns JSON) and makes sure the format of the JSON is OK.
I get an error
Error: Unable to load http://localhost:7200/users/signoff status: 0
ErrorCtor#http://localhost:9000/resources/www/tests/lib/dojo/errors/create.js:29
onError#http://localhost:9000/resources/www/tests/lib/dojo/request/xhr.js:133
I've got a service that has the actual functions to interact with the server and it returns promises from every function. My test looks like this.
define([
'intern!bdd',
'intern/chai!expect',
'app/services/myService'
], function (bdd, expect, MyService) {
with (bdd) {
describe('Service Tests', function () {
var service;
before(function () {
service = MyService.getInstance();
});
it('should sign user off', function(){
var dfd = this.async(2000);
service.signUserOff().then(dfd.callback(function (data) {
expect(data).to.exist;
expect(data.status).to.exist;
}), dfd.reject.bind(dfd));
});
});
}
});
service.signOff() makes a call to the real service and then returns a promise. I have tried this with Firefox and PhantomJS both and I keep getting this error. The weird thing is, the URL in the error works fine if loaded manually in the browser.
I wonder if this is something to do with Intern not being able to load the request/xhr.js and therefore throwing this error?
The request that you are making is considered a cross-site request, so you need to either make sure your server correctly responds with the appropriate CORS headers for such a request, or you need to set up a reverse proxy that ensures that the XHR requests are occurring through the same origin.

Meteor http calls limitations

Currently, I use the built-in meteor http method (see http://docs.meteor.com/#http) for issuing http calls, on both my client and my server.
However, I'm experiencing two issues:
is it possible to cancel a request?
is it possible to have multiple query parameters which share the same key?
Are these just Meteor limitations, or are there ways to get both to work using Meteor?
I know I could you jquery on the clientside, and there must be a server-side solution which supports both as wel, but I'd prefer sticking with meteor code here.
"is it possible to cancel a request?"
HTTP.call() does not appear to return an object on which we could call something like a stop() method. Perhaps a solution would be to prevent execution of your callback based on a Session variable?
HTTP.call("GET", url, function(error, result) {
if (!Session.get("stopHTTP")) {
// Callback code here
}
});
Then when you reach a point where you want to cancel the request, do this:
Session.set("stopHTTP", true);
On the server, instead of Session perhaps you could use an environment variable?
Note that the HTTP.call() options object does accept a timeout key, so if you're just worried about the request never timing out, you can set this to whatever millisecond integer you want.
"is it possible to have multiple query parameters which share the same key?"
Yes, this appears to be possible. Here's a simple test I used:
Meteor code:
HTTP.call("GET", "http://localhost:1337", {
query: "id=foo&id=bar"
}, function(error, result) {
// ...
});
Separate Node.js server: (just the basic example on the Node.js homepage, with a console.log line to output the request URL with query string)
var http = require('http');
http.createServer(function(req, res) {
console.log(req.url); // Here I log the request URL, with the query string
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
When the Meteor server is run, the Node.js server logged:
/?id=foo&id=bar
Of course, this is only for GET URL query parameters. If you need to do this for POST params, perhaps you could store the separate values as a serialized array string with EJSON.stringify?

Resources