Access rest api using nodejs - node.js

I am trying to access opencorporates.com and using their REST API.
I got this code from How to make remote REST call inside Node.js? any CURL?. But it is not fetching any data. I tried wget on the url and it worked perfectly fine.
app.js
var https = require('http');
var optionsget = {
host : 'opencorporates.com',
port : 8080,
path : '/v0.2/companies/search?q=barclays+bank&jurisdiction_code=gb',
method : 'GET'
};
console.info('Options prepared:');
console.info(optionsget);
console.info('Do the GET call');
var reqGET = https.get(optionsget, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
res.on('data', function(d) {
console.info('GET result:\n');
process.stdout.write(d);
console.info('\n\nCall completed');
});
});
reqGet.end();
reqGet.on('error', function(e) {
console.error(e);
});

Because Node runs asynchronously, the returned data is broken into chunks.
The .on('data') event returns a portion of the data, which you then need to stitch/append back to a variable. You can then capture the complete output with .on('end').
See this example for more info: Why is node.js breaking incoming data into chunks? (#vossad01's answer)
That said, #SilviuBurcea's suggestion to use request is a much simpler way of handling http requests so you don't have to write and handle all of this yourself.

Try using request module. https://github.com/mikeal/request It's the http module on steroids.

Tried running the code locally, and first there is a capitalization error
var reqGET = https.get(optionsget, function(res) {
reqGet.end();
Second, the web address was not working at the address, nor with secure
var optionsget = {
host : 'api.opencorporates.com',
port : 80,
path : '/v0.2/companies/search?q=barclays+bank&jurisdiction_code=gb',
method : 'GET'
};
Its worth noting that if you wanted to actually use https, you would need to change the require line
var https = require('https');

This is fully functional version for your reference:
var http = require('http');
var optionsget = {
host : 'api.opencorporates.com',
port : 80,
path : '/v0.2/companies/search?q=barclays+bank&jurisdiction_code=gb',
method : 'GET'
};
console.info('Options prepared:');
console.info(optionsget);
console.info('Do the GET call');
var reqGet = http.get(optionsget, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
buffer='';
res.on('data', function(d) {
//console.info('GET result:\n');
//process.stdout.write(d);
buffer += d.toString();
//console.info('\n\nCall completed');
});
res.on('end', function() {
console.info('GET result:\n');
console.log(buffer);
console.info('\n\nCall completed');
});
});
reqGet.on('error', function(e) {
console.error(e);
});
reqGet.end();

Related

HTTP Get Request from NodeJS

I am trying to create http get request from node, to get information from youtube URL. When I click it in browser I get json response but if I try it from node, I get ssl and other types of error. What I have done is,
this.getApiUrl(params.videoInfo, function (generatedUrl) {
// Here is generated URL - // https://www.googleapis.com/youtube/v3/videos?key=AIzaSyAm_1TROkfNgY-bBuHmSaletJhVQmkycJc&id=_H_r9qVrf24&part=id%2Csnippet%2CcontentDetails%2Cplayer%2Cstatistics%2Cstatus
console.log(generatedUrl);
var req = http.get(generatedUrl, function (response) {
var str = '';
console.log('Response is ' + response.statusCode);
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
});
req.end();
req.on('error', function (e) {
console.log(e);
});
});
I get this error
{
"error": {
"message": "Protocol \"https:\" not supported. Expected \"http:\".",
"error": {}
}
}
When I make it without https I get this error,
Response is 403
{"error":{"errors":[{"domain":"global","reason":"sslRequired","message":"SSL is required to perform this operation."}],"code":403,"message":"SSL is required to perform this operation."}}
You need to use the https module as opposed to the http module from node, also I would suggest one of many http libraries that provide a higher level api such as wreck or restler which allow you to control the protocol via options as opposed to a different required module.
Your problem is obviously accessing content served securely with http request hence, the error. As I have commented in your question, you can make use of https rather than http and that should work but, you can also use any of the following approaches.
Using request module as follow:
var url = "https://www.googleapis.com/youtube/v3/videos?key=AIzaSyAm_1TROkfNgY-bBuHmSaletJhVQmkycJc&id=_H_r9qVrf24&part=id%2Csnippet%2CcontentDetails%2Cplayer%2Cstatistics%2Cstatus";
request(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
});
Using https module you can do like below:
var https = require('https');
var options = {
hostname: 'www.googleapis.com', //your hostname youtu
port: 443,
path: '//youtube/v3/videos?key=AIzaSyAm_1TROkfNgY-bBuHmSaletJhVQmkycJc&id=_H_r9qVrf24&part=id%2Csnippet%2CcontentDetails%2Cplayer%2Cstatistics%2Cstatus',
method: 'GET'
};
//or https.get() can also be used if not specified in options object
var req = https.request(options, function(res) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
res.on('data', function(d) {
process.stdout.write(d);
});
});
req.end();
req.on('error', function(e) {
console.error(e);
});
You can also use requestify module and
var url = "https://www.googleapis.com/youtube/v3/videos?key=AIzaSyAm_1TROkfNgY-bBuHmSaletJhVQmkycJc&id=_H_r9qVrf24&part=id%2Csnippet%2CcontentDetails%2Cplayer%2Cstatistics%2Cstatus";
requestify.get(url).then(function(response) {
// Get the response body
console.log(response.body);
});
superagent module is another option
var url = "https://www.googleapis.com/youtube/v3/videos?key=AIzaSyAm_1TROkfNgY-bBuHmSaletJhVQmkycJc&id=_H_r9qVrf24&part=id%2Csnippet%2CcontentDetails%2Cplayer%2Cstatistics%2Cstatus";
superagent('GET', url).end(function(response){
console.log('Response text:', response.body);
});
Last but not least is the unirest module allow you to make http/https request as simple as follow:
var url = "https://www.googleapis.com/youtube/v3/videos?key=AIzaSyAm_1TROkfNgY-bBuHmSaletJhVQmkycJc&id=_H_r9qVrf24&part=id%2Csnippet%2CcontentDetails%2Cplayer%2Cstatistics%2Cstatus";
unirest.get(url).end(function(res) {
console.log(res.raw_body);
});
There might be more options out there. Obviously you need to load the modules using require before using it
var request = require('request');
var https = require('https');
var requestify = require('requestify');
var superagent = require('superagent');
var unirest = require('unirest');
I provided extra details, not only to answer the question but, also to help others who browse for similiar question on how to make http/https request in nodejs.

Rest API from nodejs to https url with port 8443 throwing error

I'm trying to make an API call from nodejs to tomcat server using http/https module
I have two options for api url
http://samleapiurl.com/getdata - This works fine and i'm getting reponse
var options = {
host: 'samleapiurl.com',
port: 80,
path: '/getdata'
};
http.get(options, function(resp) {
var body = '';
resp.on('data', function(chunk) {
body += chunk;
});
resp.on('end', function() {
res.end(body);
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
https://samleapiurl.com:8443/getdata
var options = {
host: 'samleapiurl.com',
port: 8443,
path: '/getdata'
};
https.get(options, function(resp) {
var body = '';
resp.on('data', function(chunk) {
body += chunk;
});
resp.on('end', function() {
res.end(body);
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
2nd option doesn't work and it throws an error like
Got error: 10232:error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert
internal error:openssl\ssl\s23_clnt.c:741:
I'm not sure why i'm getting this error if try to access 8443 in https mode.
Is there anyone who faced similar issue?
You might try restricting which ciphers tomcat can use, as noted in this blog, which suggests adding the following line to the SSL Connector section of server.xml:
ciphers="SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"

Foursquare Check-in Reply

I am trying to Connect my application to foursquare and I want to display a message when a user checks in to certain places. I am trying to use their real time api https://developer.foursquare.com/overview/realtime
Everything works fine until the very end, ( when I have to send a reply post request https://developer.foursquare.com/docs/checkins/reply) I am using express and node.js. Here is what my post request looks like.
app.post('/handlepush', function(req, res) {
var checkin_id =req.param('checkin');
console.log(checkin_id);
var obj = JSON.parse(checkin_id);
var id = obj.id;
res.end('It worked!');
var token = "********************************";
var post_data = querystring.stringify({text : "awesome"});
var options = {
host: 'api.foursquare.com',
path: '/v2/checkins/' + id + '/reply?oauth_token=' + token,
port: 443,
method: 'POST'
};
var req2 = https.request(options, function(res2) {
res2.setEncoding('utf8');
res2.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
req2.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
});
req2.write(post_data);
req2.end();
});
this is the error I get, for some reason I am not able to add parameters for my post:
BODY: {"meta":{"code":400,"errorType":"other","errorDetail":"Must provide parameter text"},"response":{}}
You need to actually send your request. See: How to make an HTTP POST request in node.js?
var req2 = http.request(options, function(res2) {
res2.setEncoding('utf8');
res2.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req2.end();

Nodejs: Unable to get response body when working with vows and nodejs http module

I am playing around vows and nodejs.
var vows = require('vows');
var http = require('http');
var suite = vows.describe('testing');
var host = 'www.google.com', port = '80', path = '/', method = 'GET';
suite.addBatch({
'A context': {
topic: function(){
http.get({
host: host,
port: port,
path: path,
method: method
}, this.callback);
},
"sample test": function(res, extra){//here extra is just to prevent vows error
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);//It never gets logged
});
console.log('HEADERS: ' + JSON.stringify(res.headers));//it is working
}
}
});
suite.export(module);
But I am unable to get the response body. What am I doing wrong.
I am using nodejs v 0.6.6 and vows v0.6.2
From what I can see, it looks like Vows doesn't directly invoke the test when this.callback runs. It is delayed by processnextTick. If I had to guess, maybe the 'data' event is being emitted during that time. That means you don't bind your 'data' function until after all the data events have been triggered.
Really though, the issue is that Vows tests are supposed to separate all async logic like this into the topic itself. If you really want to check the chunks in a test, then do it like this.
Also note that you can have any number of chunks, there isn't just a single data event. You may want to set the stream encoding, and join the data as strings. Your current code implicitly converts a Buffer to string, which can break for multi-byte characters.
suite.addBatch({
'A context': {
topic: function(){
var cb = this.callback;
var req = http.get({
host: host,
port: port,
path: path,
method: method
});
// Aggregate all chunks before running callback
req.on('response', function(res) {
var chunks = []
res.on('data', function(chunk) {
chunks.push(chunk);
});
res.on('end', function() {
cb(null, res, chunks);
});
});
// Handle connection failures.
req.on('error', cb);
},
"sample test": function(err, res, chunks){
chunks.forEach(function (chunk, i) {
console.log('BODY piece ' + i + ': ' + chunk);
});
console.log('HEADERS: ' + JSON.stringify(res.headers));
}
}
});

Pull a specific string from an HTTP request in node.js

NOOb here. I've got a HTTP request that pulls all of the content from a specific webpage. However, all I need is a specific string:"Most recent instantaneous value: ". In fact, I actually need to store the value that follows value:. Here is my code:
var http = require("http");
var options = {
host: 'waterdata.usgs.gov',
port: 80,
path: '/ga/nwis/uv?cb_72036=on&cb_00062=on&format=gif_default&period=1&site_no=02334400',
method: 'POST'
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write('data\n');
req.write('data\n');
req.end();
I realize I don't need all the console.log statements, but do I need keep console.log('BODY: ' + chunk); so all of the data downloads?
Never do it the way I'm doing it in this quick'n'dirty example. There are plenty of modules for DOM traversal, HTML/XML parsing, etc... They are a lot safer then a simple regex. But just so you get the general idea:
var http = require("http");
var options = {
host: 'waterdata.usgs.gov',
port: 80,
path: '/ga/nwis/uv?cb_72036=on&cb_00062=on&format=gif_default&period=1&site_no=02334400',
};
function extract (body, cb) {
if(!body)
return;
var matches=body.match(/Most recent instantaneous value: ([^ ]+) /);
if(matches)
cb(matches[1]);
}
http.get(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
extract(chunk, function(v){ console.log(v); });
});
}).on('error', function(e) {
console.log('problem with request: ' + e.message);
});
Somehow I also got a different page when sending a POST instead of a GET request. So I changed that bit...
Regarding your second question: No you don't need to keep any of the console.log() statements. Just use callbacks and everything is fine! :-)

Resources