I'm writing a pretty basic HTTP request using SailsJS. I'm getting the data I want from the api that I'm calling, but I can't figure out how to pass it from my service back to the controller and eventually respond to the request with the data in the body.
Here's my controller:
module.exports = {
retrieve: function(req, res) {
var output = AccountService.retrieveAccountInfo();
console.log(output);
return res.send(output);
}
}
And here is my service that I'm calling.
module.exports = {
retrieveAccountInfo: function() {
var http = require('http');
var options = {
host: 'localhost',
port: 8280,
path: '/sample/account?id=1',
method: 'GET',
headers: {
'sample': 'header'
}
};
var req = http.request(options, function(res) {
var data = '';
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers) + '\n\n');
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log('BODY: ' + chunk);
data += chunk;
});
res.on('end', function() {
console.log('hit the end');
return JSON.stringify(data);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.end();
}
}
I'm probably missing some basic JavaScript stuff here. I can get to the end callback and print "hit the end" as expected, but I can't get the data returned to the controller.
the method you're using in your service is an asynchronous method, you can modify them like following
module.exports = {
retrieve: function(req, res) {
AccountService.retrieveAccountInfo(function(error, output) {
console.log(output);
return res.send(output);
});
}
}
service - use callback method
module.exports = {
retrieveAccountInfo: function(callback) {
var http = require('http');
//.....
res.on('end', function() {
console.log('hit the end');
callback(null, JSON.stringify(data));
});
//.....
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
callback(e); //error
});
req.end();
}
}
Related
I just started working with Nodejs.
I am using Restify to get data from: http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo'.
My code below gives me an error: {"code":"ResourceNotFound","message":"/ does not exist"}
var restify =require("restify");
var server = restify.createServer();
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
server.get('http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo', function (req, res) {
console.log(req.body);
res.send(200,req.body);
});
server.listen(7000, function () {
console.log('listening at 7000');
});
That's because Restify is for creating REST endpoints, not consuming them. You should check out this SO post for help consuming data from an API.
e.g. create test.js with the following:
var http = require('http');
var options = {
host: 'api.geonames.org',
path: '/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo'
};
var req = http.get(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
// Buffer the body entirely for processing as a whole.
var bodyChunks = [];
res.on('data', function(chunk) {
// You can process streamed parts here...
bodyChunks.push(chunk);
}).on('end', function() {
var body = Buffer.concat(bodyChunks);
console.log('BODY: ' + body);
// ...and/or process the entire body here.
})
});
req.on('error', function(e) {
console.log('ERROR: ' + e.message);
});
then run node test.js.
I found what I was looking for. You can use restify client to get JSON data:
Here is my solution:
var restify = require("restify");
function getJSONDataFromUrl(){
var query = "?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo";
var options = {};
options.url = "http://api.geonames.org";
options.type = options.type || "json";
options.path = "/citiesJSON" + query;
options.headers = {Accept: "application/json"};
var client = restify.createClient(options);
client.get(options, function(err, req, res, data) {
if (err) {
console.log(err);
return;
}
client.close();
console.log(JSON.stringify(data));
return JSON.stringify(data);
});
}
getJSONDataFromUrl();
I am a beginner with node so excuse me if this question is too obvious. Also I tried the official documentation but I could resolve this problem.
My node server is communicating with an external api through a service.
This is what I ve got so far in my service api-service.js :
var http = require('http');
exports.searchNear = function(lat, long, next){
var options = {
host: '1xx.xx.1xx.1x',
path: '/api/v1/geo,
method: 'GET'
};
var req = http.request(options, function(res) {
var msg = '';
res.setEncoding('utf8');
res.on('data', function(chunk) {
msg += chunk;
});
res.on('end', function() {
console.log(JSON.parse(msg));
});
});
req.on('error', function(err) {
// Handle error
});
req.write('data');
req.end();
var mis = 'hello';
next(null, mis);
}
At this moment I can get the Json and log it in the console. But I want to store the returned json in a variable so I could pass in the next() callback.
I tried to add a callback to the end event like:
exports.searchNear = function(lat, long, next){
....
.....
var req = http.request(options, function(res) {
.....
res.on('end', function(callback) {
console.log(JSON.parse(msg));
callback(msg);
});
});
....
req.end('', function(red){
console.log(red);
});
}
Thank you in advance.
The callback's name in your code should be "next":
var http = require('http');
exports.searchNear = function(lat, long, next) {
var options = {
host: '1xx.xx.1xx.1x',
path: '/api/v1/geo,
method: 'GET'
};
var req = http.request(options, function(res) {
var msg = '';
res.setEncoding('utf8');
res.on('data', function(chunk) {
msg += chunk;
});
res.on('end', function() {
console.log(JSON.parse(msg));
next(null, msg);
});
});
req.on('error', function(err) {
// Handle error
});
req.write('data');
req.end();
}
And then you should use your function like this:
searchNear(myLong, myLat, function (err, mesg) {
console.log('your JSON: ', mesg)
});
I may be misunderstanding your question but the obvious solution is to store your parsed json in a variable and pass the variable to next()
var parsed = JSON.parse(msg);
I know how http request works and I know how to send and receive response.
This is the sample code of http request.
var http = require('http');
var options = {
host: 'www.nodejitsu.com',
path: '/',
port: '1337',
method: 'POST'
};
callback = function(response) {
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
}
var req = http.request(options, callback);
req.write("hello world!");
req.end();
In my site everything working fine Server B send request to server A and server A response to server B. But, one time I face a problem when there is huge no of traffic on server A and it was unable to receive any request from server B which halt the whole process.
So is there is any error block in request to handle this type of errors ?
I googled alot and try this type of foolish things but it does not work for me
callback = function(response,error) {
if(error){
console.log(error)
}else{
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('error', function (err) {
console.log(err);
});
}
});
Have you tried this:
var req = http.request(options,callback);
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
as given here:
http://nodejs.org/api/http.html#http_http_request_options_callback
I have the following code:
var http = require('http')
,https = require('https')
,fs = require('fs'),json;
var GOOGLE_API_KEY = process.env.GOOGLE_API_KEY;
var FUSION_TABLE_ID = "1epTUiUlv5NQK5x4sgdy1K47ACDTpHH60hbng1qw";
var options = {
hostname: 'www.googleapis.com',
port: 443,
path: "/fusiontables/v1/query?sql=SELECT%20*%20"+FUSION_TABLE_ID+"FROM%20&key="+GOOGLE_API_KEY,
method: 'GET'
};
http.createServer(function (req, res) {
var file = fs.createWriteStream("chapters.json");
var req = https.request(options, function(res) {
res.on('data', function(data) {
file.write(data);
}).on('end', function() {
file.end();
});
});
req.end();
req.on('error', function(e) {
console.error(e);
});
console.log(req);
res.writeHead(200, {'Content-Type': 'application/json'});
res.end('Hello JSON');
}).listen(process.env.VMC_APP_PORT || 8337, null);
how do i return the json object rather then the 'Hello JSON'?
Don't store the received data in a file, put it in a local variable instead, and then send that variable in res.end():
var clientRes = res;
var json = '';
var req = https.request(options, function(res) {
res.on('data', function(data) {
json += data;
}).on('end', function() {
// send the JSON here
clientRes.writeHead(...);
clientRes.end(json);
});
});
Note that you have two res variables - one for the response you're sending back to your own clients, and one which is the response you're receiving from Google. I've called the former clientRes.
Alternatively, if you're just going to proxy the information unmodified, you can just put clientRes.write(data, 'utf8') inside the res.on('data') callback:
http.createServer(function (clientReq, clientRes) {
var req = https.request(options, function(res) {
res.on('data', function(data) {
clientRes.write(data, 'utf8');
}).on('end', function() {
clientRes.end();
});
clientRes.writeHead(200, {'Content-Type: 'application/json'});
clientReq.end().on('error', function(e) {
console.error(e);
});
});
I have got some error when use http.request to make a client request(node v0.6.18, v0.6.3), the following code produces the error and I have some questions.
var http = require('http');
var url = require('url');
http.createServer(function(req, res) {
var data = '多情自古空余恨';
res.writeHead(200, {
'Content-Type': 'text/plain',
'Content-Length': 1 //ERROR
});
res.end(data);
}).listen(3000);
function request(options, callback) {
var req = http.request(options, function(res) {
var data = '';
res.setEncoding = 'utf8';
res.on('data', function(chunk) {
data += chunk;
});
res.on('error', function(err) {
callback(new Error('res error: ' + err));
});
res.on('end', function() {
console.log('res on end');
callback(null, data);
});
});
req.on('socket', function(socket) {
socket.on('error', function(err) {
console.log('socket on error');
callback('socket error: ' + err);
req.abort();
});
});
req.end();
}
request({
host: 'localhost',
port: 3000,
method: 'GET'
}, function(err, data) {
console.log('result, err: ' + err + ', data: ' + data);
});
Outputs:
res on end
result, err: null, data: �
socket on error
result, err: socket error: Error: Parse Error, data: undefined
Here are my questions:
Why res's 'end' event happened earlier than socket's 'error' event?
If I do want to callback an error when "Parse Error at Socket.ondata" happens like the above code or in any other situation, how to callback once instead of twice as the above output(IF res's 'end' event really hanppened earlier than socket's 'error' event)?
I need your help! Thanks.
===============================
I found the same code outputs:
res on end
result, err: null, data: �
in node v0.6.6 and v0.6.11. Why?
Because there's a content-length header of 1, when the request receives exactly 1 octet of data, it assumes that's all there is and fires the end callback. After that, more data is received that the socket doesn't know what to do with, so it fires the error.
To work around this, you could perhaps wait a short period before firing the callback for success and track if it's been fired. For example:
var req = http.request(options, function(res) {
var data = '';
res.setEncoding = 'utf8';
res.on('data', function(chunk) {
data += chunk;
});
res.on('error', function(err) {
if(!callback.called) { // check before firing the callback
callback(new Error('res error: ' + err));
callback.called = true; // set after firing the callback
} // ..
});
res.on('end', function() {
process.nextTick(function() { // use setTimeout if nextTick is too short
if(!callback.called) { //..
console.log('res on end');
callback(null, data);
callback.called = true; // ..
} // ..
}); // ..
});
});
req.on('socket', function(socket) {
socket.on('error', function(err) {
if(!callback.called) { // ..
console.log('socket on error');
callback('socket error: ' + err);
callback.called = true; // ..
} // ..
req.abort();
});
});
req.end();
(I tried to add comments after all of the new lines to make them stand out a little.)