nodejs socket hang up error in nested callback - node.js

I try to put many callbacks in a callback, but the program will shut down after the return of several success requests and post "socket hang up" error. I try to collect data from response and output them at once, can someone tell me which part goes wrong...
By the way, I hide the details of request method, I promise the request method works on http call.
http.request(options1,function(data){
var condition=data.length;
var result=[];
data.foreach(item,function(data){
http.request(options2, function(data){
if(data) result.push(data);
condition--;
if(condition<=0) console.log(result);
}
});
});
for my http.request method
var request=function(options,callback){
http.request(options,function(res){
var body;
res.on('data',function(chunk){
body+=chunk;
});
res.on('end',function(){
callback(JSON.parse(body));
});
request.end();
};

That's not the correct usage of http.request().
The http.request() callback is passed an IncomingMessage object, not buffered response data.
EDIT: Your custom request() should look something like this, although you should handle errors too. Note the proper placement of request.end() and initializing var body = '':
function request(options, callback) {
http.request(options,function(res) {
var body = '';
res.setEncoding('utf8');
res.on('data',function(chunk) {
body += chunk;
}).on('end',function() {
callback(JSON.parse(body));
});
}).end();
}
You're missing .end() for your requests so that node.js knows you are ready to actually send the HTTP request: http.request(..., ....).end();. This is the cause of your particular error... the server hangs up the connection because it got tired of waiting for your request after the TCP connection was opened.

Related

Incomplete JSON response with Node.js https-module

Calling the Riot-Api Im receiving incomplete JSON on a https GET-request.
After debugging, I realized that depending how much I wait (breakpoint) pre-executing the
https on'data' callback Im actually receiving the complete JSON object.
(Average API response time for me is 200-300ms)
let getOptions = function(url) {
return {
host: 'na.api.pvp.net',
port: 443,
path: `${url}?api_key=${apiKey}`,
method: 'GET'
};
}
exports.Call = function(url, callback) {
let response = {};
let req = https.request(getOptions(url), function(res) {
response.statusCode = res.statusCode;
res.on('data', function(data) {
response.json = JSON.parse(data);
callback(response);
});
});
req.on('error', function(err) {
response.err = err;
callback(response);
});
req.end();
};
Running the code without breakpoints or only breaking a short time I run either into error:
JSON.parse(data): Unexpected Token in JSON at position ...
or
JSON.parse(data): Unexptected end of JSON Input.
As I expect the 'data' callback to be executed only after the request is complete im confused about how to fix it (without artificially delaying it ofc.).
http.request returns a stream – its not a simple callback that contains the whole response.
You will have to buffer and concatenate everything if you want to parse the whole response.
I would strongly recomment to use a helper library like got or request

How to send http request with nodejs AWS Lambda?

I'm using AWS Lambda to drive an Alexa Skill Kit development. In an attempt to track events, I'd like the script to send an HTTP request on launch, however from the cloud logs it appears as though the http.get function is being skipped during the execution process.
The code is shown below (google.com replaces the analytics tracking url - which has been tested in the browser);
exports.handler = function (event, context) {
var skill = new WiseGuySkill();
var http = require('http');
var url = 'http://www.google.com';
console.log('start request to ' + url)
http.get(url, function(res) {
console.log("Got response: " + res.statusCode);
// context.succeed();
}).on('error', function(e) {
console.log("Got error: " + e.message);
// context.done(null, 'FAILURE');
});
console.log('end request to ' + url);
skill.execute(event, context);
};
The context objects have been commented out to allow for 'skill.execute' to function, yet either way this HTTP request is not executing. Only the 'start' and 'end' console.logs are recorded, those internal in the function do not.
Is this a async issue? Thanks.
You need to make sure the handler is being triggered. There are two ways of accomplishing this:
You could set up a new API endpoint and execute a request on that.
You could hit the Test button and your function would be invoked with the given data.
I copied and pasted your whole snippet except for the first and the last lines (because I don't have customSkill defined anywhere). I was able to get a 200 response code.
In order to successfully complete the http request, the http.get function must be incorporated into a callback function. Else the process will not be completed and will end prematurely, using a callback allows the http request to complete (with or without an error) before continuing with the rest of the function.
WiseGuySkill.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
// Call requestFunction to make the http.get call.
// Get response from requestFunction using requestCallback
requestFunction(function requestCallback(err) {
// If error occurs during http.get request - respond with console.log
if (err) {
console.log('HTTP Error: request not sent');
}
ContinueIntent(session,response);
});
};
The function 'requestFunction' calls http.get and fires the callback.
function requestFunction(requestCallback){
var url = "http://www.google.com";
http.get(url, function(res) {
console.log("Got response: " + res.statusCode);
requestCallback(null);
}).on('error', function (e) {
console.log("Got error: ", e);
});
}
And obviously ensure you have required 'http' at the start of the script.
Hope this helps anybody else new to this!

Node.js http.get 404 kills the app

I successfully wrote app in node.js working with http.get. Problem is, that if page doesn't exist, it make an error that terminates the app. Is any way how to declare timeout. After timeout it should stop waiting for response and let app continue (if written synchronously)
Thanks for all advices...
I'm responding thinking that you are trying to retrieve info via http.get.
You can see the validate using the response status code.
http.get(url, function(res) {
if (res.statusCode !== 200) {
Your custom handler
} else {
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
console.log(body);
});
}
}).on('error', function(e) {
console.log("error: ", e);
});
A fully implemented example can be found her https://gist.github.com/pasupulaphani/9630789
You can set timeout and emit an error/abort if the request takes too long but this has to be done in application logic.
Found a better/sophisticated solution to handle timeouts in other post :
https://stackoverflow.com/a/12815321/2073176

How to make web service calls in Expressjs?

app.get('/', function(req, res){
var options = {
host: 'www.google.com'
};
http.get(options, function(http_res) {
http_res.on('data', function (chunk) {
res.send('BODY: ' + chunk);
});
res.end("");
});
});
I am trying to download google.com homepage, and reprint it, but I get an "Can't use mutable header APIs after sent." error
Anyone know why? or how to make http call?
Check out the example here on the node.js doc.
The method http.get is a convenience method, it handles a lot of basic stuff for a GET request, which usually has no body to it. Below is a sample of how to make a simple HTTP GET request.
var http = require("http");
var options = {
host: 'www.google.com'
};
http.get(options, function (http_res) {
// initialize the container for our data
var data = "";
// this event fires many times, each time collecting another piece of the response
http_res.on("data", function (chunk) {
// append this chunk to our growing `data` var
data += chunk;
});
// this event fires *one* time, after all the `data` events/chunks have been gathered
http_res.on("end", function () {
// you can use res.send instead of console.log to output via express
console.log(data);
});
});

request.on("response",[…]) never gets fired

I'm currently messing around with NodeJS and try to use the Twitter-Search API. With curl it works fine - so there's nothing wrong with my firewall or whatever. Yet, I never get a response within NodeJS.
var sys = require("sys"),
http = require("http"),
events = require("events");
sys.puts("Hi there… ");
var client = http.createClient(80, "search.twitter.com"),
body = "",
query = "foobar";
function getResults() {
sys.puts("fetching for "+query);
var request = client.request("GET", "/search.json?q="+query);
request.on("response", function(data){
/* this somehow never gets fired :( */
sys.puts("BODY:"+ data);
});
}
var interval = setInterval(getResults, 5000);
And the URL is also working.
Any hints or solutions are welcome!
Thanks in advance.
You never send the request.
You need to use request.end()
NOTE: the request is not complete. This method only sends the header of the request. One needs to call request.end() to finalize the request and retrieve the response. (This sounds convoluted but it provides a chance for the user to stream a body to the server with request.write().)
Also the response event'S parameter is the response object NOT the body. You need to set the data event on the response object and then listen for the end event to make sure you got all the data.
request.on('response', function (response) {
var body = '';
response.on('data', function (chunk) {
body += chunk;
});
response.on('end', function () {
console.log('BODY: ' + body);
});
});
request.end(); // start the request
See: http://nodejs.org/api/http.html#http_class_http_clientrequest
A few more tips
You might want to use querystring.escape to urlencode your search parameter
You also need to set the Host header, otherwise Twitter will return a 404
Fixed code:
var querystring = require('querystring');
...
var request = client.request("GET", "/search.json?q=" + querystring.escape(query), {'Host': 'search.twitter.com'});

Resources