Node.js HTTP WebServer Write after End error - javascript

I am new to node.js and have been trying to setup just a basic server to start with.
I have the code below running and I get a "Write After End" error.
Socket.html is a basic html file that has a hello world string in the body. There is literally nothing else in that file. I have tried using the "ReadFileSync" method and that throws up a whole new set of errors that I don't fully understand.
I will appreciate any help on this. I am brand new to this so please go a little easy on me :) Thank you in advance!
I have verified that the path is correct, and that the buffer does have the data.
var http = require('http');
var url = require('url');
var fs = require('fs');
var server = http.createServer(function(request, response){
console.log('Connection');
var path = url.parse(request.url).pathname.substr(1);
path = "\\" + path;
switch(path){
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
break;
case '\\socket.html':
//console.log(path);
fs.readFile(__dirname + path, function(error, data){
if(error){
response.writeHead(404);
response.write("This domain is missing");
}
else{
console.log(data);
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data,"utf8");
}
});
break;
default:
response.writeHead(404);
response.write("This domain is missing");
break;
}
response.end();
});
server.listen(8001);

I think when you read from the FileSystem async, the response.end() method is called before response.write() I would suggest using the following code instead:
var http = require('http');
var url = require('url');
var fs = require('fs');
var server = http.createServer(function(request, response) {
var path = url.parse(request.url).pathname.substr(1);
path = "\\" + path;
switch(path) {
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
response.end();
break;
case '\\socket.html':
fs.readFile(__dirname + path, function(error, data) {
if(error) {
response.writeHead(404);
response.write("This domain is missing");
} else {
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data, "utf8");
}
response.end();
});
break;
default:
response.writeHead(404);
response.write("This domain is missing");
response.end();
break;
}
});

Related

Why does this node.js code fails if there is no blank return at the end of catch()?

I've been learning Node and although I understand all the code, and what is does, one thing is bothering me. So this is the code:
const http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');
// array of mime types
var mimeTypes = {
"html" : "text/html",
"jpeg" : "image/jpeg",
"jpg" : "image/jpeg",
"png" : "image/png",
"js" : "text/javascript",
"css" : "text/css"
}
// create Server
http.createServer( (req, res) => {
var uri = url.parse(req.url).pathname;
var fileName = path.join(process.cwd(),unescape(uri));
console.log('Loading ' + process.cwd() + uri);
var stats;
try{
stats = fs.lstatSync(fileName);
} catch(err) {
res.writeHead(404, {'Content-Type' : 'text/plain'});
res.write('404 Not found\n');
res.end();
return; // if I remove this my code fails.
}
// check if file or directory
if (stats.isFile()) {
var mimeType = mimeTypes[path.extname(fileName).split(".").reverse()[0]]
res.writeHead(200, {'Content-Type': mimeType});
var fileStream = fs.createReadStream(fileName);
fileStream.pipe(res);
} else if (stats.isDirectory()) {
res.writeHead(200 , {
"Location" : "index.html"
});
res.end();
} else {
res.writeHead(500, {"Content-Type" : "text/plain"});
res.write("500 Internal Error\n");
res.end();
}
}).listen(8080);
So If I remove blank return inside catch block my code will fail.
With return:
Without return:
Does return allows execution to continue, can anyone explain?
Thanks.
If you will not return inside the catch block - the code will continue to run and will get to the following line:
stats.isFile()
Now, stats is not defined, since there was an exception there, so your code is actually undefined.isFile(), and this will throw another exception there.
I think you expect that the res.end() will stop the function execution / request processing, but instead it only closes the response body. The response then can be returned but your code after try / catch block goes on and experiences problems. The only proper way to stop the execution is your return; statement.

Formidable is not defined in Node.js

I am trying to create an HTTP server that the user can upload images and archives, and for that I am using formidable for handling the upload part.
My code :
requestHandler.js
// Request Handlers (will handle all requests that happen)
// Allows Node.js to make use of a non-blocking operation: exec ();
var exec = require("child_process").exec;
var querystring = require("querystring");
fs = require("fs");
var fomidable = require("formidable");
function start(response, postData) {
console.log("Request handler 'start' was called");
var body = '<html>' +
'<head>' +
'<meta http-equiv = "Content-Type" content = "text/html";'+
'charset="UTF-8"/>' +
'</head>' +
'<body>' +
'<form action = "/upload" enctype = "multipart/form-data"' +
'method = "post">' +
'<input type ="file" name = "upload multiple = "multiple">' +
'<input type = "submit" value ="Upload file" />' +
'</form>' +
'</body>' +
'</html>';
response.writeHead(200, {"Content-Type" : "text/html"});
response.write(body);
response.end();
}
// What is being passed between router.js and requestHandler.js is the entire body of the POST data request.
function upload(response, request) {
console.log("Request handler 'upload' was called");
var form = new formidable.IncomingForm();
console.log("about to parse");
form.parse(request, function(error, fields, files) {
console.log("parsing done");
/*Possible error on Windows systems; tried to rename to an already existing file*/
fs.rename(files.upload.path, "/tmp/test.png", function(err) {
if(err) {
fs.unlink("/tmp/test.png");
fs.rename(files.upload.path, "/tmp/test.png");
}
});
response.writeHead(200, {"Content-Type" : "text/plain"});
response.write("You've sent the text : " + querystring.parse(postData).text);
response.write("\nHello Upload");
response.end();
});
}
function show(response) {
console.log("Request handler 'show' was called.");
fs.readFile("/tmp/test.png", "binary", function(error,file) {
if(error) {
response.writeHead(500, {"Content-Type" : "text/plain"});
response.write(err + "\n");
response.end();
} else {
response.writeHead(200, {"Content-Type" : "image/png"});
response.write(file, "binary");
reponse.end();
}
});
}
exports.start = start;
exports.upload = upload;
exports.show = show;
I am using too formidable in the another part of my code, in my server.js but there for some reason works (And for that reason I am not posting the code), the error point out to requestHandler.js in line 35 :
var form = new formidable.IncomingForm();
formidable is not defined
How can I make formidable defined ? When I am already doing that calling in the first place in :
var formidable = require("formidable");
I think you have a typo...
var fomidable = require("formidable");
Should probably be:
var formidable = require("formidable");
Hence the formidable is not defined... you defined it as fomidable.

memory error in node JS (node::smalloc::Alloc)

I'm new to node Js, I've build a really simple server that send me back a zip file I request. It's all working but after some request a crash occur and i visualize this message on the terminal :
FATAL ERROR: node::smalloc::Alloc(v8::Handle, size_t, v8::ExternalArrayType) Out Of Memory
var http = require('http');
var url = require('url');
var fs = require('fs');
var port = 1337;
// create http server
var server = http.createServer(function (request, response) {
var path = require('url').parse(request.url, true);
console.log('requested ' + path.pathname);
//get zipped resoures
if (path.pathname == '/getzip') {
console.log(request.url);
var queryData = url.parse(request.url, true).query;
if (queryData.name) {
var filename = queryData.name;
//open corrisponding file
var zipFile = fs.readFileSync('packets/' + filename);
response.writeHead(200, {
'Content-Type': 'application/x-zip',
'Content-disposition': 'attachment; filename=data.zip'
});
//send file in response
response.end(zipFile);
}
else {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('{error = "bad url"}');
}
}
}).listen(port);
server.timeout = 1000000;
Do you have any idea of what it can be? this code looks so simple.
Instead of reading the entire file into memory, you should leverage streams for this:
response.writeHead(200, {
'Content-Type' : 'application/x-zip',
'Content-disposition' : 'attachment; filename=data.zip'
});
fs.createReadStream('packets/' + filename).pipe(response);

Response.write() not returning value

I've been following this tutorial for an introduction on nodejs, but I'm having trouble returning something with response.write().
My server.js code works fine in returning "hello world" when I go to domain:8001, but navigating to domain:8001/socket.html returns a blank screen.
I've used console.log to check that the code to write "socket is here." is being executed, but I'm not sure why it isn't doing anything.
server.js:
var http = require("http");
var url = require('url');
var fs = require('fs');
var server = http.createServer(function(request, response){
console.log('Connection');
var path = url.parse(request.url).pathname;
console.log(__dirname);
console.log(path);
switch(path){
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
break;
case '/socket.html':
fs.readFile(__dirname + path, function(error, data){
if (error){
response.writeHead(404);
response.write("opps this doesn't exist - 404");
}
else{
response.writeHead(200, {"Content-Type": "text/html"});
response.write("socket is here.");
}
});
break;
default:
response.writeHead(404);
response.write("opps this doesn't exist - 404");
break;
}
response.end();
});
server.listen(8001);
var io = require('socket.io').listen(server);
socket.html: (though it shouldn't matter what is contained in it)
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<script>
var socket = io.connect();
</script>
<div>This is our socket.html file</div>
</body>
</html>
You're ending the response before waiting for fs.readFile() to complete. Try this:
var http = require("http");
var url = require('url');
var fs = require('fs');
var server = http.createServer(function(request, response){
console.log('Connection');
var path = url.parse(request.url).pathname;
console.log(__dirname);
console.log(path);
switch(path){
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
break;
case '/socket.html':
fs.readFile(__dirname + path, function(error, data){
if (error){
response.writeHead(404);
response.write("opps this doesn't exist - 404");
}
else{
response.writeHead(200, {"Content-Type": "text/html"});
response.write("socket is here.");
}
response.end();
});
return;
default:
response.writeHead(404);
response.write("opps this doesn't exist - 404");
break;
}
response.end();
});
server.listen(8001);
var io = require('socket.io').listen(server);
Also, doing fs.readFile(__dirname + path, ...); is potentially dangerous because someone could send a request like /../../../../../../etc/passwd. What you should do there instead is use the path module to resolve/normalize __dirname + path to an absolute path, and then ensure that that absolute path starts with the absolute path of your public directory.

detect ajax request to normal request node js

hello h have the next code and i like to know how to detect between an ajax request to a normal request? without express.
var http = require('http');
var fs = require('fs');
var path = require('path');
var url = require('url');
http.createServer(function (request, response) {
console.log('request starting...');
console.log("request.url = " + request.url);
console.log("url = "+ url);
response.setHeader('content-Type','application/json');
var filePath = '.' + request.url;
if (filePath == './')
filePath = './index.html';
var extname = path.extname(filePath);
var contentType = 'text/html';
switch (extname)
{
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
}
fs.exists(filePath, function(exists) {
if (exists)
{
fs.readFile(filePath, function(error, content) {
if (error)
{
response.writeHead(500);
response.end();
}
else
{
console.log("contentType = "+contentType);
response.writeHead(200, { 'content-Type': contentType });
response.end(content, 'utf-8');
}
});
}
else
{
response.writeHead(404);
response.end();
}
});
}).listen(8081);
console.log('Server running at http://localhost:8081/');
in the client side i send an ajax request but i ask from the browser request to.
You can check request.headers if it contains HTTP_X_REQUESTED_WITH.
If HTTP_X_REQUESTED_WITH has a value of XMLHttpRequest then it is an ajax request.
Example:
if (request.headers["x-requested-with"] == 'XMLHttpRequest') {
//is ajax request
}
I came across this question and I know it's old but in case someone needs the answer and the idea behind it.
Usually, on the client side, when you make an AJAX request you add a key and value that describe the content i.e: 'content type':'application/json'
So simply, on the server side, you can test the header if it contains application/json as the content type then you are safe to say it's an ajax request.
req.headers['content-type'] == 'application/json'

Categories