Normally in angular.js I was used to consuming a web service GET, in which I passed 2 parameters, as follows.
$http.get('https://maps.googleapis.com/maps/api/geocode/json?latlng='+tweet.lat+','+tweet.long+'&key=AIzaSyBZVOSPh0Z4mv9jljJWzZNSug6upuec7Sg')
.then(function(result){
}, function(error){
}
How can I get this same result directly in nodejs?. thank you very much.
There are several way to do this. A lot of people use the request module, which makes things about the same as angular:
You'll need to install request (https://www.npmjs.com/package/request) with:
npm install request
and then:
var request = require('request');
request(url, function (error, response, body) {
// do stuff with response & body.
});
If you want promises, there is also a request-promise module available on npm (https://www.npmjs.com/package/request-promise).
npm install --save request
npm install --save request-promise
You need both request and request-promise in this case.
var request = require('request-promise');
request(url)
.then(function (result) {
// do stuff with result
})
.catch(function (err) {
//error
});
Also you can use the http module built into node, but then you'll need to manage the stream yourself.
Related
I am newbie in firebase admin SDK and trying to get it work on my angularjs app, using and following the steps here and this here:
I have correctly setup my firebase admin SDK and initialized it like this in server.js file on my node server:
var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<DATABASE_NAME>.firebaseio.com"
});
app.post('/.firebase-user', function (req, res, nex) {
admin.auth().getUser(req.body.uid)
.then(function (userRecord) {
// See the tables below for the contents of userRecord
console.log("Successfully fetched user data:", userRecord.toJSON());
})
res.status(200).send({data: userRecord.toJSON()});
return nex();
.catch(function (error) {
console.log("Error fetching user data:", error);
res.status(117);
return nex();
});
});
now I want to access userRecord.toJSON() inside my controller:
$http.post('/.firebase-user', {uid: firebase.auth().currentUser.uid})
.then(function(response) {
console.log($scope.data, response.userRecord);
});
But it is not printing the userRecord.toJSON(), instead I get true undefined in the console.
Please help me to fetch the info back inside my app. thanks
It looks like there are a few issues with your (Express) app request handler:
In your Angular code, you make a request to the /.fb endpoint but in your server code you are listener on the /.firebase-user endpoint. I assume you want these to both be the same.
Your server code never actually sends a response to the Angular code. I'm surprised your then() completion handler ever actually completes. You should need to explicitly send a response with something like res.status(200).send(userRecord.toJSON()) in the success case and res.status(400).send({ error: error }) in the error case.
You should add a catch() to your Angular code to ensure you are catching any errors or failed requests being made by the server code.
I have an angular application making async requests to an API service. Since a lot of the resources are protected on the API Service, I need to intercept the HTTP requests made to the service. But as far as I can see, the interceptor I have defined only intercept page load requests.
Here is an experimental setup I have come up with to illustrate my problem:
myApp = angular.module('myApp', []);
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(function() {
return {
response: function(response) {
console.log(response);
return response;
}
};
});
});
What I am able to see is that, the interceptor intercepts all calls except the API call as you can see from the attached screen shot showing the console output.
The console output, as you can see from the screen shot below, contains the responses logged when the partial templates have been loaded but not when the GET request was made to the API service.
Why does this happen?
Update
I have changed my setup to include all possible combinations of requests and responses now:
$httpProvider.interceptors.push(function() {
return {
request: function(request) {
console.log(request);
return request;
},
requestError: function(request) {
console.log(request);
return config;
},
response: function(response) {
console.log(response);
return response;
},
responseError: function(response) {
console.log(response);
return response;
}
};
});
Now the interceptor intercepts the message but weirdly shows the status of the caught responseError as:
status: -1
although it clearly is a 401.
Update 2
As it turns out, even 401 responses require the CORS header to be added to it. The problem came up since the REST API I was calling used Spring-CORS library which does not include CORS headers on 401 and 403 responses.
It's a cross-site domain issue because although your using localhost your API call domain is different to the UI's (port 8080 & 8081), have a read of this article for more information. You will need add this header in your webserver:
Access-Control-Allow-Origin: http://foo.example
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Is it possible to test the response from NodeJs using Mocha?
A GET request is made using $http from AngularJs to NodeJs. On success of the request this function is called:
var successCallback = function (data) {
var SUCCESS_STATUS_CODE = 200;
response.set('Content-Type', 'application/json');
response.send({
statusCode: SUCCESS_STATUS_CODE,
data: data
});
};
I have tried to use Sinon to spy on the function and also Mocha to check the request but I cannot get them to work. What is the best way to write a test to check that the output from "response.send"?
To test a response of a HTTP call from Node.JS, you could use superagent
Create a folder and install inside mocha and superagent:
$ npm install superagent
$ npm install mocha
Then create a file called something like test.js with this code:
var request = require('superagent');
var assert = require('assert');
var URL = 'https://www.google.com.bo/#q=nodejs';
describe('Testing an HTTP Response', function () {
it('should have a status code 200', function (done) {
this.timeout(9000);
request
.get(URL)
.end(function (err, response) {
assert.equal(response.status, 200);
done();
});
});
});
then you can run it with mocha
$ mocha
I'm executing an $http.get over websockets and somehow the .error doesn't populate any of the parameters. I'm using angular 1.3.5 and latest Chrome on OSX and local host is aliased to mywebsite.com.
$http({method: 'GET', 'ws://mywebsite.com/resource'})
.success(function(response){ ... })
.error(function(err, status){
console.log(err); <<< here err and status are null respectively 0 even the XHR Response logs 401 in console.
});
Any clues why this is doing so? No mater what error code it is, it doesn't get passed to error callback. For 2xx response i do get the data and all is fine.
Just to clarify, the .error callback gets called as normal, but err and status re not populated.
Well, well, I discovered what was happening. A combo of things.
First I'm using KOA and the above angular hits the KOA as REST API. I'm also using koa-jwt to auth the users and generate a token.
Now the api runs on a subdomain and even i set the CORS via koa-cors to allow * access.
The issue is that koa-jwt when the token is expired, they simply do a this.throw(401). The way KOA handles that it so immediately terminate subsequent middleware and exit with that error. THAT, didn't allow koa-cors headers to be set, regardless where I put that middleware (before or after koa-jwt).
Hence, the elegant fix was to wrap my top level yield next in a try catch and avoid allowing koa-jwt ctx.throw to propagate.
On Angular side, the browser was refusing to convey the 401 to the .error complaining it didn't find a suitable CORS to allow it to process and hand over the response :).
app.use(cors({origin:"*", methods:'GET,HEAD,PUT,POST,DELETE,PATCH'})); //allow all origins to the API.
app.use ( function *(next){
try {
yield next;
} catch (err) {
this.status = err.status || 500;
this.body = err.message;
this.app.emit('error', err, this);
}
});
... more middleware
// middleware below this line is only reached if jwt token is valid
app.use(jwt({secret: config.app.secret}));
Allowing a this.trow(401) from koa-jwt will ruin your day.
I think you just make a typo, just write like this:
$http({method: 'GET', 'ws://mywebsite.com/resource', headers: headers})
.success(function(response){ ... })
.error(function(err, status){
console.log(err);
});
However as a best practice I would do as
var request = {
method: 'GET',
url: 'ws://mywebsite.com/resource',
headers: {//insert here header you want, put Origin header only for example purposes
Origin: 'ws://mywebsite.com/resource'
}
}
$http(request)
.success(function(response){ ... })
.error(function(err, status){
console.log(err);
});
If the typo is not the error (you may copied the code) just look at this AngularJS $http error function never called
I'm using angular-http-auth to show a login dialog whenever a 401 "unauthorized" response is returned from the server.
Since I'm cool, I also try to deserialize response objects in my services. For example, if a service requests a car and the response is {make: Honda, model: Civic}, I try to deserialize that into a Car object using transformResponse.
For example:
getCar: function() {
return $http.get('/api/car', {
method: 'GET',
transformResponse: function(data, headers) {
var c = angular.fromJson(data);
return new Car(c);
}
});
}
This doesn't work with angular-http-auth. If the response was a 401 Unauthorized, you'll get a javascript error. It's because angular will try to run that transformResponse code even if the response was a 401.
It turns out that $http interceptors (which is what angular-http-auth uses) are run AFTER the transformResponse code. That's a huge problem, because none of that code in transformResponse will work if the server response was a 401 (there wouldn't be any data)
Is this a problem for anyone else? How did you get around it? Am I not to use transformResponse if I use $http interceptors?
Late to the party, I know, but to anyone coming here from Google like I did (I also posted this as a comment on a related issue filed with the Angular repo):
I also found it to be confusing that response interceptors run after the transformResponse method. I added a method to $http.defaults.transformResponse. Here is an example from the documentation on how to do that.
So, if you need to basically have a response interceptor that runs before the transformResponse method, this should do it:
'use strict';
angular.module('app')
.run(function ($http) {
$http.defaults.transformResponse.push(function (data, headers) {
// do stuff here before the response transformation
// Be sure to return `data` so that the next function in the queue can use it.
// Your services won't load otherwise!
return data;
});
});
If your services or http calls don't have their own response transformer, you're good now.
If your services do have their own transformResponse method, they will actually override all default transformers (I found this out after a long read of the documentation), and the above code will not run.
To circumvent this, you can follow this example in the docs.
To get around this problem I don't use transformResponse anymore. I just can't see the point of transformResponse if it runs before $http interceptors.
In order to use angular-http-auth and also deserialize responses in your services, you can write your services so that they execute the HTTP request first and then deserialize the response in a callback function.
As an example, here is how I would have restructured the example in the OP:
Plunker
services.factory('HttpCarService', function($resource, $q) {
var resource = $resource('/api/car');
return {
getCar: function() {
var deferred = $q.defer();
var car = null;
var successCallback = function(data, status, headers, config) {
var c = angular.fromJson(data);
car = new Car(c);
deferred.resolve(car);
};
var errorCallback = function(data, status, headers, config) {
deferred.reject("something wrong");
};
var result = resource.get(successCallback, errorCallback);
return deferred.promise;
}
};
});
This pattern will also work if data is an array.
$http interceptors will run before either of the callback methods are executed. If your $resource needs url params, you can make the getCar() function accept a config object as a parameter, and pass the necessary information on when you make the $resource.get() call.