I'm learning Node.js and I'd like to understand the "why" when code spits out duplicated console.log outputs but only a single response.write outputs.
Heres my simple code example:
var http = require('http');
http.createServer(function(request, response){
response.writeHead(200, {'Content-type': 'text/plain'});
console.log('hello 1');
response.write('Hello world');
console.log('hello 2');
response.end();
}).listen(8000);
And on my console/terminal I get:
hello 1
hello 2
hello 1
hello 2
Thanks.
Some browsers also send a request to locate the favicon.ico file. Since the file isn't present by default, a browser(Chrome in particular) will always send two requests: one for the originally requested file and another for favicon.ico. This is a known bug in Chrome and has been fixed in version 29. Firefox, however, requests for favicon.ico only for the first request. If you console.log the request URI path, you must see a request to localhost:8000/favicon.ico.
var http = require('http');
http.createServer(function(request, response){
response.writeHead(200, {'Content-type': 'text/plain'});
if(request.url === '/favicon.ico') {
console.log('Favicon was requested');
}
console.log('hello 1');
response.write('Hello world');
console.log('hello 2');
response.end();
}).listen(8000);
I've had the same problem myself, and I found out that using something like
var http = require('http');
http.createServer(function(req,res) {
if(req.url === '/favicon.ico')
{
//everything here is ignored
}
res.writeHead(200,{"Content-Type": "text/plain"});
res.write("Hello World\n");
res.end();
console.log("Connection made");
}).listen(1337, "127.0.0.1");
console.log("Server running at http://127.0.0.1:1337/");
is enough to avoid that behaviour. For some reason, when I check req.url and compare it to '/favicon.ico' nothing is sent to console, in fact, everything in that block is ignored. I don't know if this behaviour is expected, but you sure could try it.
If you output the header you're telling the server that you found favicon, hence the response is processed and no matter what you get that double console.log(). Instead, end it before sending a writeHead() or send a 404.
var http = require('http');
http.createServer(function (req, res) {
if(req.url === '/favicon.ico') {
res.writeHead(404);
res.end();
} else {
res.writeHead(200, {'Content-Type': 'text/plain'});
}
//code here...
res.end();
}
i think that this problem still persists in chrome Version 67.0.3396.87 (32-bit) because when i ran my nodeJS script i saw 2 console.log() statements one was able to print out the query the other was not, so i corrected my code so as to see console.log() statements only once, it was simple all i had to do was add a return statement if the request.url was == (equal to)"/favicon.ico" in the beginning of the code and everything worked fine
previous code
var http = require('http');
var url = require('url');
http.createServer((request,response)=>{
var q = url.parse(request.url,true).query;
console.log(request.url);
console.log('hey there! we got a request from '+q.name+' !');
}).listen(8080);
and the output was :
/?name=harshit
hey there we got a request from harshit !
/favicon.ico
hey there we got a request from undefined !
code after debugging :
var http = require('http');
var url = require('url');
http.createServer((request,response)=>{
if(request.url == "/favicon.ico"){
return ;
}
var q = url.parse(request.url,true).query;
console.log(request.url);
console.log('hey there! we got a request from '+q.name+' !');
}).listen(8080);
output :
/?name=harshit
hey there we got a request from : harshit !
in a nutshell the duplication as it is mentioned before is a result of the favicon request so to avoid this problem, I propose you this simple snipet:
var pathname = url.parse(request.url).pathname;
if(pathname != '/favicon.ico')
console.log('hello 1');
It can also be a Chrome plugin like JSONView. I was just trying to figure it out until I tried incognito and realized it was no longer causing the problem. Also was requesting a JSON file.
Related
Im self-educating Node.js. I have created two simple HTML files (summer.html and winter.html) and noded the JS on node.js. I went on localhost:5354/summer.html (and winter.html). Nothing is showing up and I got an error message
This site can’t be reached
The connection was reset.
Try:
Checking the connection
Checking the proxy and the firewall
Running Windows Network Diagnostics
ERR_CONNECTION_RESET
I have tested other lessons and was able to display results on localhost:5354/ but this one doesnt work. What did I do wrong?
JS
var http = require('http');
var url = require('url');
var fs = require('fs');
http.createServer(function (req, res) {
var q = url.parse(req.url, true);
var filename = "." + q.pathname;
fs.readFile(filename, function(err, data) {
if (err) {
res.writeHead(404, {'Content-Type': 'text/html'});
return res.end("404 Not Found");
}
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
return res.end();
});
}).listen(5343);
Hit this URL
localhost:5343/summer.html
Because, You listen in 5343 PORT. But you hit 5354 Port
To show my students a simple HTTP request and response that they could capture using Wireshark, I whipped up a simple Node.js HTTP server:
var fs = require('fs');
var http = require('http');
var port = 80;
var file = process.argv[2]; //This file contains a 42 byte HTML page
http.createServer(function (req, res) {
res.writeHead(200, { 'content-type' : 'text/html' }); // Sends first packet
fs.createReadStream(file).pipe(res); // Sends second packet
}).listen(port);
Unfortunately, the two lines transmitting the HTTP header and the HTML are sent as two separate TCP packets (even though they are both quite small). It would be simpler for my students if the HTTP header and HTML were just one packet. How could I change my code to do this?
var http = require('http');
var fs = require('fs');
var file = process.argv[2];
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html;"});
fs.readFile(file, function (err, html) {
if (err) {
throw err;
}
response.write(html);
response.end();
});
}).listen(8000);
the reason it won't work is that Node.js runs everything asynchronously. When you are loading your html file, the server creation starts the same time. By the time you are about to write your html to your tcp socket, the file most likely won't be ready.
I see what you were trying to do before... I misread your code because of the indentation. Let me know if this snippet works.
try using something like-
var file = process.argv[2];
fs.readFile(file, function (err, html) {
if (err) {
throw err;
}
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(8000);
});
I have an HTTP server setup on port 1338 to listen on the IP for the server. This works just fine when I first launch Node, but for some reason I have run into issues where the server randomly stops listening. I have checked the logs that Forever is collecting from my app including any uncaught exceptions. Nothing shows up in the logs of having any error since startup.
My question is two fold. What would cause the server to stop listening at random intervals? Also what check should be running in Node so that I can log out the error that is causing the listener to stop?
Here is the code below for my HTTP Server.
http.createServer(function (req, res) {
var pathname = url.parse(req.url).pathname;
var query = url.parse(req.url, true).query;
var check;
var responseData = '';
if(pathname === '/healthcheck/ticket'){
check = new Date().getTime();
check = check - tickets.lastAction;
if(check < 30000){
responseData = "page ok";
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(responseData);
}
else{
check = check/1000;
responseData = 'Last action taken by the Ticket Generator was ' + check + ' seconds ago';
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(responseData);
}
}
else{
responseData = 'URL NOT FOUND!';
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end(responseData);
}
}).listen(config.eng.port, config.eng.host);
You don't handle the case when pathname is not equal to /healthcheck/ticket. There is no else branch.
Hence, when your server gets called with other urls but /healthcheck/ticket, it never closes the res stream, as res.end() is never called.
After a while, your server runs out of (network) resources, and hence seems to hang (i.e., it does not react on new requests any longer).
The solution is simple: Provide an else branch, and call res.end() in it, and everything should be fine.
On nodejs.org socket.setTimeout, it says
When an idle timeout is triggered the socket will receive a 'timeout' event but the connection will not be severed.
But when I test code like this:
var http = require('http');
server = http.createServer(function (request, response) {
request.socket.setTimeout(500);
request.socket.on('timeout', function () {
response.writeHead(200, {'content-type': 'text/html'});
response.end('hello world');
console.log('timeout');
});
});
server.listen(8080);
The socket is closed immediately after timeout, and no data is replied to the browser. Which is quite different from the document. Is this a bug or is there any tricks dealing socket under http module?
The documentation is indeed correct, however it looks like the http module adds a 'timeout' listener which calls socket.destroy(). So what you need to do is get rid of that listener by calling request.socket.removeAllListeners('timeout').
So your code should look like:
var http = require('http');
server = http.createServer(function (request, response) {
request.socket.setTimeout(500);
request.socket.removeAllListeners('timeout');
request.socket.on('timeout', function () {
response.writeHead(200, {'content-type': 'text/html'});
response.end('hello world');
console.log('timeout');
});
});
server.listen(8080);
I have a case where i have to read the data from the request body and create a file and write the data into it. If the operation is successful I set the response header to 201 and add the location of file in Location header. The file creation is done using Java methods and node.js code is below.
var server = http.createServer(function(req, res)
{
var body = "";
req.on("data", function(chunk)
{
body += chunk.toString();
});
req.on("end", function() {
var rtn = obj.AddonPostMethod(filepath,body);
if(rtn.length < 13)
{
res.writeHead(201, {"Location" : rtn});
res.end();
}
else
{
res.writeHead(400, {"Content-Type" : application/json"});
res.write(''+rtn);
res.end();
}
});
}});
The problem is that the response headers are not getting updated and are always set to the default headers 200 Ok. In addition to this the server is always busy even after the response is received.
I don't think you're actually listening on a port with the code you reference.
var http = require('http');
http.createServer(function(req,res){
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8000);
console.log('Server running at http://127.0.0.1:8000/');
You never declare the http object as actually listening on a port/ip with the .listen() function.
Also, you don't need to wait for the req object to emit anything to respond. The function is called when the request is complete. You can listen for specific requests and route them appopriately by storing the http.Server object to a variable.
var server = http.createServer();
server.listen(8000);
server.on('request', function(req,res){ /* do something with the request */ });
More documentation on the http object can be found on the node.js documents for http