I've picked up Node.js recently. Before I jump to Express.js and other web frameworks, I learned few things about them but I wanted to try some API programming. I downloaded this module: https://www.npmjs.com/package/steamwebapi
Since I'm new to Node.js, I made new javascript file, app.js and my code is:
var SteamWebAPI = require('steamwebapi').SteamWebAPI;
SteamWebAPI.setAPIKey('My key is here');
SteamWebAPI.getRecentlyPlayedGames('76561198190043289', 5, function(response) {
console.log(response);
});
SteamWebAPI.getRecentlyPlayedGames('76561198190043289', 5, function(response) {
console.log(response);
});
'76561198190043289' is my steam 64 id. When I type: node app.js in terminal, I get:
{ response: { total_count: 1, games: [ [Object] ] } }
{ response: { total_count: 1, games: [ [Object] ] } }
How do I display my results, what I'm doing wrong?
You are not doing anything wrong. console.log makes the output more compact for the sake of readability. It can get very lengthy at times so it's probably a good thing.
It means that "[ [Object] ]" is actually an array of one or more games. You can try using
console.dir( response );
instead, or you can be more specific with log:
console.log( response.response.games );.
There are other ways around this as well if you can bother to search around. Converting to a string seems to be popular:
console.log( JSON.stringify( response, null, 4) );
Off topic...
I would also like to mention something else (since you are new) the one thing everyone must relearn coming to node from js. Calling functions like you do:
function1(..., callback);
function2(..., callback);
Node moves on to the second function immediately without waiting for the first callback to finish. So you have no idea of which of those functions will finish first. To force the order you would have to do this:
SteamWebAPI.getRecentlyPlayedGames('76561198190043289', 5, function(response) {
console.log(response);
SteamWebAPI.getRecentlyPlayedGames('76561198190043289', 5, function(response) {
console.log(response);
});
});
Your code will turn into the infamous callback hell. There is no avoiding it. It will happen sooner or later! To prevent that, learn how to use promises. You'll be much better off going from there!
Edit: Connect to angular
You need to create a server-backend of some kind. This is how it could look like using express (since you mention express):
var express = require('express');
var server = express();
var SteamWebAPI = require('steamwebapi').SteamWebAPI;
SteamWebAPI.setAPIKey('My key is here');
// define endpoints
server.get('/games', function (req, res) {
SteamWebAPI.getRecentlyPlayedGames('76561198190043289', 5, function(response) {
res.json(response.response.games);
});
});
// Start the server
server.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Once it's running you can test that it works by browsing to http://example.com:3000/games
Then you call your endpoint from angular:
var app = angular.module("app", []);
app.controller("myCtrl", function($scope, $http){
$scope.games = [];
$http.get('http://example.com:3000/games').then(function(response){
// The response is seldom exactly what you expect. Check your browser console.
console.log(response);
$scope.games = response.data;
});
});
html
<body ng-app="app" ng-controller="myCtrl">
<div ng-repeat="game in games">{{ game }}</div>
</body>
All done.
Mind you, this is all shooting from the hip (no testing whatsoever) , so there are bound to be errors. But it should give you a starting point at least.
Related
I searched for a good example of Node+Express+Oracle. I need to read values from an Oracle view to create the response to a GET operation.
Most examples does not use "Express" (my choice of framework) and simply log the database information. Here are some of the best I found : from Express, from Oracle 1, from Oracle 2
Here is the one I preferred to base my code on. I like it because it includes Express, and actual manipulation of the response data. Sadly, it still does not work for me. And I am wondering what the issue is.
I think I understand the asynchronous nature of the JavaScript language (ie: callbacks), and I am beginning to suspect my problem might be tied to : A stupid variable name snafu, My version of Oracle (12c) or the fact that the source is a view (replicated from another schema).
I tried the following code in many other forms (including async functions), and also tried to switch from node 10 to 11... no changes.
Any help would be welcomed.
As of now, the code "works", in the sense that the row data from the database is printed on screen, but the response in Postman (my test tool) is empty, with no http error code... just like the connection would have been cut before replying.
Note the commented, misplaced response code, that returns a response if uncommented (and then crashes the program since the header is written twice).
Here is the code.
It is based on this project/file (and simplifed):
var express = require('express');
var oracledb = require('oracledb');
var app = express();
var connAttrs = {
"user": "user",
"password": "pass",
"connectString": "some_host/SCHEMANAME"
}
// Http Method: GET
// URI : /myObj
app.get('/myObj', function (req, res) {
"use strict";
oracledb.getConnection(connAttrs, function (err, connection) {
if (err) {
// Error connecting to DB
res.set('Content-Type', 'application/json');
res.status(500).send(JSON.stringify({
status: 500,
message: "Error connecting to DB",
detailed_message: err.message
}));
return;
}
// THIS works if uncommented. This is obviously the wrong place to put this.
//res.contentType('application/json').status(200);
//res.send("Test.1.2");
connection.execute("SELECT * FROM SCHEMA.SOMEVIEW", {}, {
outFormat: oracledb.OBJECT // Return the result as Object
}, function (err, result) {
if (err) {
res.set('Content-Type', 'application/json');
res.status(500).send(JSON.stringify({
status: 500,
message: "Error getting the user profile",
detailed_message: err.message
}));
} else {
//log first row... THIS WORKS !
console.log(result.rows[0]);
//This does not work, like if "res" could not be touched here !!!
res.contentType('application/json').status(200);
res.send(JSON.stringify(result.rows[0]));
}
// Release the connection
connection.release(
function (err) {
if (err) {
console.error(err.message);
} else {
console.log("GET /myObj: Connection released");
}
});
});
});
});
var server = app.listen(3000, function () {
"use strict";
var host = server.address().address,
port = server.address().port;
console.log(' Server is listening at http://%s:%s', host, port);
});
Here is a representation of the console:
{ field1: 'some data',
field2: 'some more data' }
GET /myObj : Connection released
And here is the behaviour in postman:
ARGGG ! It was a simple timeout ! Postman DOES mention it as a possibility (see image), but I would like the program to make it flash it bright letters !!!
Closing the question. Sorry for the disturbance.
I have a meteor application hosted on modulus.
Modulus has an api here: https://api.modulus.io/
The API code is hosted here: https://github.com/onmodulus/modulus-cli/blob/master/lib/librarian/librarian.js#L361
I want to save a domain to one of my deployments on modulus through the API.
I know this is the code I am looking to connect to: https://github.com/onmodulus/modulus-cli/blob/master/lib/librarian/librarian.js#L361
librarian.project.saveDomains = function(projectId, domains, authToken, callback) {
if(checkInit(callback)) {
librarian._http.request(util.format('/project/%s/domains?authToken=%s', projectId, authToken), 'POST', domains, callback);
}
};
And I am new to making API calls.
I believe I need to make the call from the server in my meteor app, which could be handled using a meteor method, but I don't know what the API call should look like.
I've researched online and on SO. No luck and I am battling a lack of experience with API calls so I am looking from a little direction.
I've added the http package for meteor:
meteor add http
I think the following is in the ball park, but not currently working:
POST
javascript
//save arguments object to options variable
var options = {
projectId: xxx,
domains: ["example.com"],
authToken: settings.Modulus.authToken
}
//call meteor method from client
Meteor.call('saveDomainToModulus', options, function(error, result) {
if (error)
console.log(error)
else
console.log(result)
}
});
//on server
Meteor.methods({
"saveDomainToModulus": function(options) {
var apiEndpoint = "http://api.modulus.io/project/%s/domains?authToken=" + options.authToken;
HTTP.post( apiEndpoint,
options.projectId,
options.domains,
options.authToken,
function( error, response ) {
if ( error ) {
console.log( error );
} else {
console.log( response );
}
});
}
})
Feels like I'm starting to close in on a solution, but if anyone with more experience has any feedback, let me know.
I don't even know if that question makes sense. I don't have a lot of experience with socket.io or deployd. You'll probably understand what I'm trying to do from my code. It's similar to this. Here is my server code.
var deployd = require('deployd');
var options = {
//options go here
};
var dpd = deployd(options);
dpd.listen();
dpd.on('getLobby', function (lobby) {
dpd.lobby = lobby; //trying to bind variable to socket
console.log('get Lobby');
});
dpd.on('disconnect', function() {
console.log("disconnected");
});
dpd.on('connection', function (socket) {
console.log('connection');
});
and on my client side I have this
dpd.socket.emit('getLobby', lobby, function (data) {
console.log("emitted");
console.log(data);
});
The server works. My app works. Everything runs fine except for this code. I get no errors and no console logs. None of this code seems to work at all. It doesn't seem to emit and it doesn't seem to catch an emission if there even is one. I have tried lots of different ways of writing this.
I'm trying to write tests for my npm module, which takes care of communicating with my backend api. this module will sit inside a cordova android app, and will take care of any api calls. the issue that i'm having seems to be an understanding of mocha, but i've had a good look around the internet and can't find a solution so i turn to the masses. As an example, i have a function like
test: function() {
request.get({
url: defaultHost,
headers: {
}
}, function(err, httpResponse, body) {
if(err) {
return err;
} else {
console.log(body);
return body;
}
});
}
this works will. i'm now trying to create the test for it in mocha. the problem that i'm getting is that i have no idea how to get the return function from the .get call into the mocha test. the api returns json, so i know that i'm going to have to be doing an is equal comparison, but at the moment i can't even get it to print the results. i think the problem with is that with my other mocha tests that i can get working, they all have an argument that you pass in where as this doesn't. my current code for the test looks like this.
describe('#test', function() {
it('tests api reachability;', function() {
var test = new test();
});
});
if someone can explain what is required afterwards or even just point me in the right direction on google, that would be awesome. i'm normally pretty good at the google, but failing to find direction on this one.
I think nock will solve this issue. Let's assume you sending get request to some resource (http://domain.com/resource.json) and the tests would be like this:
var nock = require('nock');
// ...
describe('#test', function() {
beforeEach(function () {
nock('http://domain.com')
.get('resource.json')
.reply(200, {
message: 'some message'
});
});
it('tests api reachability;', function() {
var test = new test();
});
});
I'm writing an API wrapper for an external API, to be used in our application.
I have adopted a test-driven approach for this project but since I have little to no experience with writing API wrappers, I'm not sure if I'm on the right track.
I understand that I should not be testing the external API, nor should I be hitting the network in my tests. I'm using Nock to mock my requests to the API.
However, I'm not sure I'm doing this correctly.
I made some requests to the API using curl and put the (XML) response in a file, for example: /test/fixtures/authentication/error.js:
module.exports = "<error>Authorization credentials failed.</error>"
Since I don't want to hit the network, but want to make sure my wrapper parses the XML to JSON, I figured I needed sample data.
My test looks like this:
describe("with an invalid application key", function() {
var cl, api;
before(function(done) {
api = nock(baseApi)
.get('/v1/auth/authenticate')
.reply(200, fixtures.authentication.error);
done();
});
after(function(done) {
nock.cleanAll();
done();
});
it("returns an error", function(done) {
cl = new APIClient(auth.auth_user, auth.auth_pass, "abcd1234");
cl.authenticate(function(err, res) {
should.exist(err);
err.should.match(/Authorization credentials failed./);
should.not.exist(res);
api.isDone().should.be.true;
done();
});
});
});
With my tested code looking like this:
APIClient.prototype.authenticate = function(callback) {
var self = this;
request({
uri: this.httpUri + '/auth/authenticate',
method: 'GET',
headers: {
auth_user: this.user,
auth_pass: this.pass,
auth_appkey: this.appkey
}
}, function(err, res, body) {
if (err) {
return callback('Could not connect to the API endpoint.');
}
self.parser.parseXML(body, function(err, result) {
if (err) { return callback(err); }
if (result.error) { return callback(result.error); }
self.token = result.auth.token[0];
return callback(null, result);
});
});
};
Now, this seems to be working fine for the authentication side of things (I also have a 'success' fixture, which returns the 'success' XML and I check if the returned JSON is actually correct.
However, the API I'm using also has endpoints like:
/data/topicdata/realtime/:reportxhours/:topics/:mediatypes/:pageIndex/:pageSize
I'm not sure how to test all (should I?) possible combinations with URLs like those. I feel like I can hardly put 30 XML responses in my fixtures directory. Also, when mocking responses, I'm afraid to miss out on possible errors, edge cases, etc. the external API might return. Are these valid concerns?
If anyone has any pointers, and/or knows of any open-source and well-tested API wrappers I could take a look at, I'd be very grateful.
I think your concern is very valid and I suggest you to also build tests using Zombie or other simular request-based testing frameworks.