nodejs Error: Parse Error at Socket.ondata - javascript

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.)

Related

AWS Lambda: Error: getaddrinfo ENOTFOUND from api

I have created the following code which grabs a seralizedXmlFile object from an S3 bucket and pushes it to a api service. This returns FAIL with the logs showing
Error: getaddrinfo ENOTFOUND http://url
at errnoException (dns.js:28:10)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)
CODE:
const AWS = require('aws-sdk');
const https = require('http');
var s3 = new AWS.S3();
var un;
var pw;
var seralizedXmlFile;
let index = function index(event, context, callback) {
//for testing I have named the bucket and key
var params = {
Bucket: "bucket", //event.bucketName,
Key: "personnelData_50112404_635705766849654385.xml" //event.fileName
};
s3.getObject(params, function(data, err)
{
if (data)
{
let seralizedXmlFile = err.Body.toString('utf-8'); // Use the encoding necessary
console.log("objectData " + seralizedXmlFile);
}
});
var ssm = new AWS.SSM({region: 'ap-southeast-2'});
var paramsx = {
'Names' : ['/App/ServiceUsername', '/App/ServicePassword'],
'WithDecryption' : true
};
ssm.getParameters(paramsx, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else {console.log('data: ' + JSON.stringify(data)); // successful response
console.log('password: ' + data.Parameters[0].Value);
console.log('username: ' + data.Parameters[1].Value);
pw = data.Parameters[0].Value;
un = data.Parameters[1].Value;
}
const req = https.request('http:/url/api/SyncPersonnelViaAwsApi/Get/5', (res) => {
res.headers + 'Authorization: Basic ' + un + ':' + pw;
let body = seralizedXmlFile;
console.log('Status:', res.statusCode);
console.log('Headers:', JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
console.log('Successfully processed HTTPS response');
console.log('returned res: ' + res);
callback(null, res);
});
});
req.end();
});
};
exports.handler = index;
I followed a Q and A I found on AWS Lambda: Error: getaddrinfo ENOTFOUND
and changed the code to
var params = {
host: "http://URL",
path: "/api/SyncPersonnelViaAwsApi/Get/5"
};
var req = https.request(params, function(res) {
let data = '';
console.log('STATUS: ' + res.statusCode);
res.setEncoding('utf8');
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function() {
console.log("DONE");
console.log(JSON.parse(data));
but again firing the same error....does anyone have any idea what the issue is?
I have also tested the web service api through POSTMAN, so I can confirm it is working
Thank You
Try
host: "URL",
instead of
host: "http://URL",
Also, you're using the https library and your URL prefix is http:// but I think you can/should omit it altogether.
Error: getaddrinfo ENOTFOUND http://url
means client was not able to connect to given address. Please try specifying host without http:
var params = {
host: "URL",
path: "/api/SyncPersonnelViaAwsApi/Get/5"
};

node js :Can\'t set headers after they are sent

How to send the response properly. I like to move to another page after FTP and Telnet sessions.
Even tried using res.redirect function too. While using res.redirect, i commented window.location= "SaveRedirect"; line, in javascript of html page. Even then, I get the same error.
Here presenting the code snippet,
the javascript code in html
IPData ={
"DeviceIpAddr": "192.168.1.2"
};
function processSave() {
$.post("PostSave", IPData, function(data) {
window.location= "SaveRedirect";
});
return true;
}
node js code snippet
app.get('/SaveRedirect', function (req, res) {
res.sendFile( __dirname + "/" + "Page2.htm" );
})
var bodyParser = require('body-parser');
var testJsonEncoder = bodyParser.json();
urlEncoded = bodyParser.urlencoded({ extended: true });
app.post('/PostSave', testJsonEncoder,urlEncoded, function(request, response){
var LoginData = JSON.stringify(request.body, null, 4);
console.log(LoginData);
FormDataObj = JSON.parse(LoginData);
gDeviceIpAddress = FormDataObj.DeviceIpAddr;
console.log("IP Address" + gDeviceIpAddress);
console.log("FTP to linux box...");
ftpFile(gDeviceIpAddress, "PUT", "temp_data.json", response);
console.log("FTP temp_data file to linux box... Done!");
TelnetLinux(gDeviceIpAddress);
console.log("Telnet to linux box... Done!");
response.send("just to send response");
//response.json(LoginData);
});
function ftpFile(ftpIPAddr, operation, filename, resp) {
console.log("ftpIPAddr = " + ftpIPAddr);
ftpConfig.host = ftpIPAddr;
// Handle error
ftpClient.on("error", function (err) {
console.log(" - ERROR HANDLE - \n");
console.log(err);
resp.send("FAIL: " + err.message);
ftpClient.end();
});
// Handle error
ftpClient.on("ready", function () {
console.log("Connected....\n");
if(operation == "GET") {
console.log("filename : " + filename);
ftpClient.get(filename, function(err, stream) {
if (err)
{
resp.send("FAIL: " + err.message + " - " + filename);
ftpClient.end();
//throw err;
}
else {
stream.once('close', function() { ftpClient.end(); });
stream.pipe(fs.createWriteStream('test_data.json'));
resp.send("SUCCESS: file received");
ftpClient.end();
}
});
}
if(operation == "PUT") {
ftpClient.put(filename, filename, function(err) {
if (err) {
resp.send("FAIL: " + err.message + " - " + filename);
ftpclient.end();
throw err;
}
else {
resp.send("SUCCESS: file sent");
ftpClient.end();
}
});
}
});
ftpClient.connect(ftpConfig);
}
function TelnetLinux(deviceIPAddr) {
var telnetParams = {
host: deviceIPAddr,
port: 23,
username: "webtest",
password: "test123",
shellPrompt: '$',
timeout: 1500,
// removeEcho: 4
};
cmd = "ls";
console.log("Telnet Address : " + deviceIPAddr);
telnetClient.on('ready', function(prompt) {
telnetClient.exec(cmd, function(err, response) {
//console.log(response);
console.log("Cmd executed !");
});
});
telnetClient.on('timeout', function() {
console.log('telnet socket timeout!')
telnetClient.end();
});
telnetClient.on('close', function() {
console.log('telnet connection closed');
});
telnetClient.connect(telnetParams);
}
Error :
c:\WebTest>node webapp.js
Example app listening at http://:::8081
IP Address192.168.1.2
FTP to linux box...
ftpIPAddr = 192.168.1.2
FTP temp_data file to linux box... Done!
Telnet Address : 192.168.1.2
Telnet to linux box... Done!
Cmd executed !
telnet socket timeout!
telnet connection closed
Connected....
_http_outgoing.js:346
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)
at ServerResponse.header (c:\WebTest\node_modules\express\lib\response.js:719:10)
at ServerResponse.send (c:\WebTest\node_modules\express\lib\response.js:164:12)
at c:\WebTest\webapp.js:222:11
at Object.cb (c:\WebTest\node_modules\ftp\lib\connection.js:1017:13)
at Parser.<anonymous> (c:\WebTest\node_modules\ftp\lib\connection.js:117:20)
at emitTwo (events.js:100:13)
at Parser.emit (events.js:185:7)
at Parser._write (c:\WebTest\node_modules\ftp\lib\parser.js:59:10)
at doWrite (_stream_writable.js:301:12)
at writeOrBuffer (_stream_writable.js:287:5)
at Parser.Writable.write (_stream_writable.js:215:11)
at Socket.ondata (c:\WebTest\node_modules\ftp\lib\connection.js:273:20)
at emitOne (events.js:90:13)
at Socket.emit (events.js:182:7)
at readableAddChunk (_stream_readable.js:153:18)
This happens when you try to do res.send (or response.send) multiple times in the same call. I believe it has to do with this bit of code:
app.post('/PostSave', testJsonEncoder, urlEncoded, function(request, response) {
var LoginData = JSON.stringify(request.body, null, 4);
console.log(LoginData);
FormDataObj = JSON.parse(LoginData);
gDeviceIpAddress = FormDataObj.DeviceIpAddr;
console.log("IP Address" + gDeviceIpAddress);
console.log("FTP to linux box...");
ftpFile(gDeviceIpAddress, "PUT", "temp_data.json", response);
console.log("FTP temp_data file to linux box... Done!");
TelnetLinux(gDeviceIpAddress);
console.log("Telnet to linux box... Done!");
response.send("just to send response");
//response.json(LoginData);
});
You're doing a response.send at the end of this function, and again in ftpFile()
Since you are sending response multiple times in app.post("/Postsave" and function ftpFile for the same request, you get this error.
To resolve this, I would suggest you to send the result(or error) from the ftpfile back to the app.post(i.e., through callback) and then based on the result or error send the response from the app.post function.

http authentication using request module of nodejs returning undefined body

Trying to hit the following http-auth code:
var auth = require("http-auth");
var basic = auth.basic({
realm: "Authentication required",
file: __dirname + "/../htpasswd"
});
http.createServer(basic, onRequest).listen(port);
The following is the code snippet that's hitting the above logic with request library of nodejs:
var request = require('request'),
username = "username",
password = "password",
url = "http://localhost:3000/",
auth = "Basic " + new Buffer(username + ":" + password).toString("base64");
request(
{
url : url,
headers : {
"Authorization" : auth
}
},
function (error, response, body) {
console.log("body "+body);
console.log("response "+response);
console.log("error "+error);
}
);
Output:
response : undefined
body : undefined
error : socket hang up
Stack trace:
events.js:141
throw er; // Unhandled 'error' event
^
Error: socket hang up
at createHangUpError (_http_client.js:203:15)
at Socket.socketOnEnd (_http_client.js:288:23)
at emitNone (events.js:72:20)
at Socket.emit (events.js:166:7)
at endReadableNT (_stream_readable.js:893:12)
at doNTCallback2 (node.js:429:9)
at process._tickCallback (node.js:343:17)
onRequest method:
module.exports.start = function(route, handle) {
function onRequest(request, response){
// response.write("welcome "+request.user+"!");
var pathname = url.parse(request.url).pathname;
route(handle, pathname, request, response);
}// on request ends here
onRequest is called from app.js like this:
var router = require("./lib/router.js");
var handle = {}
handle["/add"] = requestHandler.addMethod;
handle["/delete"] = requestHandler.deleteMethod;
handle["/edit"] = requestHandler.editMethod;
handle["/search"] = requestHandler.searchMethod;
console.log(router.route);
server.start(router.route, handle);
router.js
"use strict";
var url = require("url");
module.exports.route = function(handle, pathname, request, response) {
if(typeof handle[pathname] === 'function') {
handle[pathname](request, response);
} else {
console.log("no request handler found for "+pathname);
}// else ends here
}// route ends here
Method from the handler (requestHandler):
module.exports.addMethod = function (req, res) {
body = "";
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
body = JSON.parse(body);
databaseConnection.collection("productList").insert(body, function(err,data) {
if(err){
res.writeHead(400, {"contentType":"application/JSON"});
var failedRes = JSON.stringify({
error : {
text : "Failed to add product"
}
});
res.end(faileRes);
return;
}// error handling
res.writeHead(200, {"Content-Type": "application/JSON"});
var finalId = data.ops[0]._id;
var successRes = JSON.stringify({
data: {
id : finalId
},
error : {
code : 0,
text : "Product added successfully"
}
});
res.end(successRes);
});
})
}
The error occurs because of a JSON.parse error on the server. The body object is a string but it is not a valid JSON string. This causes the line:
JSON.parse(body);
to throw an error on the server (if not data was sent):
SyntaxError: Unexpected end of input
at Object.parse (native)
or, if data was sent:
SyntaxError: Unexpected token ...
at Object.parse (native)
Either of these errors cause the server to crash and, consequently, the client to report the socket hang up error.
To resolve this, you'll need to send the data to the server as JSON. To do this with the request module:
request.post(url, {
headers: {
"Authorization" : auth
},
json: {
message: 'Hello'
}
}, function (error, response, body) {
console.log("body "+body);
console.log("response "+response);
console.log("error "+error);
});

Sending data from Sails Service to a Controller

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();
}
}

HTTP Request in Node Js

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

Categories

Resources