if i go to localhost:8080/?referal=referalID in my console i got referall id and also one line of undefined value, how can i remove that undefined line?
var http = require('http');
var url = require('url');
http.createServer(function(req,res){
res.writeHead(200, {'Content-Type':'text/html'});
var adr = req.url;
var q = url.parse(adr, true);
var qdata = q.query;
res.end(console.log(qdata.referal));
}).listen(8080);
my question is what i need to change here?
I'm not sure what you're trying to do there, however this should be the correct syntax:
var http = require('http');
var url = require('url');
http.createServer(function(req,res) {
var adr;
var q;
var qdata;
req.on('data', function() {
// Data handler
}).on('end', function() {
res.writeHead(200, {'Content-Type':'text/html'});
adr = req.url;
q = url.parse(adr, true);
qdata = q.query;
console.log(qdata);
res.end(qdata.referal);
});
}).listen(8080);
You cannot send a console.log call in the response.
You should separate the two:
console.log(qdata.referal); // This will print in the console, server side
res.end(qdata.referal) // This will be echoed back to the client, in the browser
The reason you see undefined is because your browser is also looking for favicon.ico so your function gets hit twice. If you do:
var http = require('http');
var url = require('url');
http.createServer(function(req,res){
res.writeHead(200, {'Content-Type':'text/html'});
var adr = req.url;
console.log(adr);
var q = url.parse(adr, true);
var qdata = q.query;
res.end(qdata.referal);
}).listen(8080);
you will get:
/?referal=referalID
/favicon.ico
The result of url.parse('/favicon.ico', true); is undefined.
Also as others mentioned res.end(console.log(qdata.referal)); won't return anything to the browser/client because console.log() doesn't return anything.
The undefined line you probably talking about is the one returns to the client, that's because console log doesn't return anything
as you can see in the source code here
Override console logging to return the arguments
['log', 'warn', 'error'].forEach(function(method) {
var oldMethod = console[method].bind(console);
console[method] = function() {
oldMethod.apply(console, arguments);
return arguments;
};
});
Although this might save couple opcodes and pushing another object into the stack, you should use this with caution or memorize a pray that will help you with future-related-bugs.
Next time, please attach log or screenshot
#over-programming
Related
I have just started out learning Node js. I can't understand why in output.txt I am seeing "2020 Septemberundefined undefined" in output.txt when I call:
http://localhost/?month=September&year=2020
I am expecting to see just "2020 September" in output.txt.
var http = require('http');
var url = require('url');
var fs = require('fs');
//create a server object:
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
var q = url.parse(req.url, true).query;
var txt = q.year + " " + q.month;
fs.appendFile('output.txt', txt, function (err) {
// nothing
});
res.end(); //end the respons
}).listen(8080); //the server object listens on port 8080
The favorite icon. Add console.log(req.url). You will see that the browser makes two requests.
Browser is sending requests for http://localhost:8080/favicon.ico, behind the scenes.
So whenever you hit http://localhost:8080/?month=September&year=2020,
node write "2020 September" to output.txt file, meanwhile browser hit favicon.ico request then node write again "undefined undefined" in output.txt file.
if you want to skip favicon.ico request,
var http = require('http');
var url = require('url');
var fs = require('fs');
//create a server object:
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
if (req.url != '/favicon.ico') {
var q = url.parse(req.url, true).query;
var txt = q.year + " " + q.month;
fs.appendFile('output.txt', txt, function (err) {
// nothing
});
}
res.end(); //end the respons
}).listen(8080);
I'm new to node and got stuck with handling multiple async tasks.
Except from node, I've got another server (S1) which doesn't return data immediately to requests, it can returns multiple types of data and also can send notifications without requesting them specifically, so node have to listen to data from it , parse it and act accordingly.
The connection to this server (S1) is done by using:
S1 = net.createConnection({'host':S1Host, 'port': S1Port});
And node listens to data with:
S1.on('data', function(data){
S1DataParse(data);
});
I have to route the correct data (after parsing it) to a specific POST request.
app.post('/GetFooFromS1', function(req, res){
// Send request to S1
S1.write({'type':'foo'});
// If got the correct data sometime in the future, send response to the browser
res.setHeader('Content-Type', 'application/json');
res.json({'status':'success', 'value':S1FooData});
});
I tried to use the async module for that, but with no success.
What I was trying to do:
var asyncTasks = [];
app.post('/GetFooFromS1', function(req, res){
asyncTasks.push(function(callback){
// Send request to S1
S1.write({'type':'foo'});
});
async.parallel(asyncTasks, function(response){
res.setHeader('Content-Type', 'application/json');
res.json({'status':'success', 'value':response});
});
});
and another task in S1DataParse:
function S1DataParse(){
if(data.type='foo'){
asyncTasks.push(function(callback){
callback(data);
});
}
}
But, of course, the second task never added to the asyncTasks array. I really got stuck with that.
Can you please help me with that?
Thanks
-=-=-=- Edit -=-=-=-
Eventually, I came accross with events and EventEmitter().
From the POST request I call the function that sends requests to the data server (DataServerClientGet).
In this function I register a listener which will get the future data.
eventEmitter.on('getData', returnDataServerData);
It all works great except for one thing. Whenever I refresh the page or add other POST requests, I get an error:
Error: Can't set headers after they are sent.
It would be great if I solve this problem. Help me, please.
Thanks ;)
The whole code looks like this:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var bodyParser = require('body-parser')
var net = require('net');
var events = require('events');
var dataServerHost = '127.0.0.1';
var dataServerPort = 12345;
var dataServerClient;
var logMsg;
var eventEmitter = new events.EventEmitter();
/*******************************************/
// Init
/*******************************************/
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static(__dirname + '/public'));
/*******************************************/
// Connect to the data server
/*******************************************/
DataServerConnect();
/*******************************************/
// Open listener on port 3000 (to browser)
/*******************************************/
http.listen(3000, function(){
logMsg = 'listening on *:3000';
console.log(logMsg);
});
/*******************************************/
// Routing
/*******************************************/
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
app.post('/GetDataFoo', function(req, res){
var msg;
var size;
msg ='\n{"Type":"Query", "SubType":"GetDataFoo","SearchFilter":""}';
size = msg.length;
logMsg = 'Client to DataServer: GetDataFoo';
console.log(logMsg);
DataServerClientGet('GetDataFoo', size, msg, res);
});
/*******************************************/
// Functions
/*******************************************/
function DataServerConnect(){
dataServerClient = net.createConnection({'host':dataServerHost, 'port': dataServerPort}, function(){
logMsg = 'Connected to DataServer ['+dataServerHost+':'+dataServerPort+']';
console.log(logMsg);
});
dataServerClient.on('data', function(data){
logMsg = 'DataServerData>>>\n'+data.toString()+'DataServerData<<<';
console.log(logMsg);
DataServerDataParse(data.toString());
});
dataServerClient.on('end', function(){
logMsg = 'Disconnected from DataServer';
console.log(logMsg);
});
}
function DataServerClientGet(type, size, msg, res){
dataServerClient.write('Type: Json\nSize: '+size+'\n\n'+msg, function(err){
var returnDataServerData = function returnDataServerData(results){
res.setHeader('Content-Type', 'application/json');
res.json({'status':'success', 'value':results});
}
eventEmitter.on('getData', returnDataServerData);
}
function DataServerDataParse(json){
if(json.Type=='GetDataFoo')
{
var MessageList = json.MessageList;
eventEmitter.emit('getData', MessageList);
}
}
-=-=-=- Edit -=-=-=-
The Error: Can't set headers after they are sent. caused by adding the same listener of the same type each time the DataServerClientGet was called and the res was sending multiple times.
I solved this one by adding: removeListener(event, listener)
right after the res, inside the function. Anyway, I think it's wrong and can cause problems if there will be multiple calling to DataServerClientGet with the same type etc.
There is a optional callback parameter that you can pass to write function(docs), something like :
S1.write({'type':'foo'},function(err){
if(err){
//Handle error
}else{
res.setHeader('Content-Type', 'application/json');
res.json({'status':'success', 'value':response});
}
})
This can work with post route , but in your 'data' listener ,you cant send data from server to client when there is not connection initialized by client (it is not bidireccional ) if you want bidireccional behavior you can check socket.io
I have a very simple javascript using Node. The purpose of the script is to:
Open a listening socket
Add a handler for URL /test with HTTP function GET
When /test is requested another URL located on another external web site should be fetched. This web site is encoded with ISO-8859-1
The data returned from the external website should be packaged in a JSON structure and returned to the requesting client encoded with UTF-8
So far I have created the following code:
var Buffer = require('buffer').Buffer;
var iconv = require('iconv-lite');
var urllib = require('url');
var restify = require('restify');
var server = restify.createServer();
server.use(restify.bodyParser());
server.get('/test', test);
server.listen(8080, function() {
console.log('%s listening at %s', server.name, server.url);
});
function test(req, res, next) {
console.log('TEST');
var httpClient = restify.createStringClient({ url: "http://dl.dropboxusercontent.com" });
httpClient.get("/u/815962/iso-8859-1.html", function(cerr, creq, cres, cdata) {
cdata = iconv.decode(cdata, 'iso-8859-1');
res.send(200, {"Data": cdata});
});
}
I have set up a test document used in the code above. The test document is in ISO-8859-1 encoding and has the national letters "ÅÄÖåäö" inside it. When returned to the client, if read like UTF-8 I receive "ýýýýýý"
It really seem that this is a bug in Restify. The following example shows different results using Restify and Request lib:
var request = require('request');
var iconv = require('iconv');
var restify = require('restify');
var ic = new iconv.Iconv('iso-8859-1', 'utf-8');
request.get({ url: 'http://dl.dropboxusercontent.com/u/815962/iso-8859-1.html', encoding: null, }, function(err, res, body) {
var buf = ic.convert(body);
var utf8String = buf.toString('utf-8');
console.log(utf8String);
});
var httpClient = restify.createStringClient({ url: "http://dl.dropboxusercontent.com" });
httpClient.get("/u/815962/iso-8859-1.html", function(cerr, creq, cres, cdata) {
var buf = ic.convert(cdata);
var utf8String = buf.toString('utf-8');
console.log(utf8String);
});
I have browsed the code of Restify on github trying to find the issue, but I can't
When I am trying to run the code from below:
var express = require('express');
var app = express();
var port = process.env.PORT || 5000;
var request = require('request');
var zlib = require('zlib');
app.listen(port, function() {
console.log("Listening on " + port);
makeRequest();
});
function makeRequest(){
var url = 'https://api.stackexchange.com/2.1/search?pagesize=5&order=desc&sort=activity&intitle=ios development&site=stackoverflow';
var headers = {'Accept-Encoding': 'gzip'};
var response = request(url, headers);
gunzipJSON(response);
}
function gunzipJSON(response){
var gunzip = zlib.createGunzip();
var json = "";
gunzip.on('data', function(data){
json += data.toString();
});
gunzip.on('end', function(){
parseJSON(json);
});
response.pipe(gunzip);
}
function parseJSON(json){
var json = JSON.parse(json);
if(json.items.length){
for(var i in json.items){
console.log(json.items[i].title + '\n' + json.items[i].link);
}
}
}
I get error saying
Error: incorrect header check
at Zlib._binding.onerror (zlib.js:286:17)
I am passing my own gzipped url in the code.
Any help will be really useful.
Thanks
Old question (and request library is now deprecated), but better late than never:
Interestingly, the code in question does work for me on Node.js version 15.13.0, but not on 14.16.0 (keeping the version of request the same, which is the latest 2.88.2).
However, just using the following simple code works on 14.16.0 (live demo), but not on 15.13.0!:
request(url, function (error, response, body) {
console.log(JSON.parse(body));
});
This means that for some reason, on 14.16.0 the response body is automatically unzipped (hence the above snippet works), while on 15.13.0 the response body is kept compressed and so an active decompression is needed.
In most examples you find on the web, an index.html file is served like the following:
function serveIndexPage(response) {
fs.readFile('__dirname + /public/index.html', function (err, data) {
response.end(data);
});
};
This seems like a bad idea, as the whole file is read into memory and then send to the client. Is there some better way to do this? I know that libaries like Connect and Express provide such a functionality, but for my project, I'd like to use plain node.js.
EDIT
Also, you sometimes see readFileSync used, which is even worse IMHO.
Pipe your data through, so a simple static HTTP server looks like:
var Http = require('http'),
Url = require('url'),
Path = require('path'),
Fs = require('fs');
Http.createServer(function(req, res) {
var path = Url.parse(req.url).pathname;
var file = Path.join(process.cwd(), path);
path.exists(filename, function(exists) {
if(!exists) {
res.writeHead(404);
res.end();
}
res.writeHead(200, /* mime type */);
var fileStream = Fs.createReadStream(filename);
fileStream.pipe(res);
});
}).listen(process.env.PORT || 1999);
The pipe'ing is shorthand for something like
var s = Fs.createReadStream(filename);
s.on('data', function (data) {
res.write(data);
});
s.on('end', function() {
res.end();
});
In theory you could read the file line by line response.write()'ing every line to the client.