Headers, Node.js , Can\'t set headers after they are sent - javascript

I'm new in node.js and I'm implementing a Static file server.
what i'm trying to do is just get the file name from the url and display it. running the code id get this error:
_http_outgoing.js:489
throw new Error('Can\'t set headers after they are sent.');
Error: Can't set headers after they are sent.
this is my code
#!/usr/bin/env node
/*
* Basic node.js HTTP server
*/
const http = require('http');
const url = require('url');
const fs = require('fs');
const routes = Object.create(null);
function file(rew, res, serched) {
let fileSerched = serched[serched.length - 1]
fileSerched = __dirname + "/NodeStaticFiles/" + fileSerched;
fs.readFile(fileSerched, function(err, data) {
if (err) {
res.statusCode = 500;
res.end(`Error getting the file: ${err}.`);
} else {
res.setHeader('Content-type', 'text/plain');
res.writeHead(200)
res.end(data);
}
})
}
routes['file'] = file;
function onRequest(req, res) {
const pathname = url.parse(req.url).pathname
const uri = pathname.split('/', 3)[1]
let splittedPathname = pathname.split('/')
splittedPathname.shift()
splittedPathname.shift()
if (typeof routes[uri] === 'function') {
routes[uri](req, res, splittedPathname);
} else {
res.statusCode = 404;
res.end(`File not found!`);
}
res.end()
}
http.createServer(onRequest).listen(3000);
console.log('Server started at localhost:3000')

You need to make sure your code won't call something like res.end() more than once. For example:
function onRequest(req, res) {
const pathname = url.parse(req.url).pathname
const uri = pathname.split('/', 3)[1]
let splittedPathname = pathname.split('/')
splittedPathname.shift()
splittedPathname.shift()
if (typeof routes[uri] === 'function') {
routes[uri](req, res, splittedPathname);
} else {
// THIS WILL CALL res.end() and continue on
res.statusCode = 404;
res.end(`File not found!`);
}
// THIS WILL CALL res.end() AGAIN!!
res.end()
}
try adding a return after you call res.end() in an if/else

Related

Routing for static site causes endless loading in browser when readFile() is in an if statement

I am trying to create routing for a static site however placing readFile() in an if statement causes infinite loading in my browser and content doesn't load.
I'm trying to do this without the use of Express or any similar framework.
Here is my code:
var http = require("http");
var fs = require("fs");
var url = require("url");
var path = require("path");
var server = http.createServer((req, res) => {
let parsedURL = url.parse(req.url, true);
let fPath = parsedURL.path;
if (fPath === "/") {
fPath = "/index.html";
}
file = path.join(__dirname, "/public" + fPath);
if (fPath === "/index.html") {
fs.readFile(file, (err, data) => {
if (err) {
console.error(err);
res.end("An error has occured.");
} else {
res.end(data);
}
});
} else if (fPath === "/information.html") {
fs.readFile(file, (err, data) => {
if (err) {
console.error(err);
res.end("An error has occured.");
} else {
res.end(data);
}
});
}
});
server.listen(8000);
If if (fPath === "/index.html") { matches and fs.readFile has an error, then you don't send a response.
The same is true for "/information.html".
And if fPath isn't either of those then you get to the end and you don't send a response.
The endless loading is caused by the browser waiting for a response you never send.
You need to make sure that every path through your if statements calls res.end or another function that sends a response to the browser.

First argument must be of type string or an instance of buffer or uint8array. Received undefined

I made this code and after everything I try it keeps giving me this error.
First argument must be of type string or an instance of buffer or uint8array. Received undefined
Excuse me for being new at Node.js, but I really don't know where I went wrong. I thank you for your help.
function createServer(obj){
var i;
obj.port = (obj.port || 8080);
obj.path = (obj.path || "/");
http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/html'});
for(i in obj.path){
fs.readFile(i, "utf-8", (err, data) => {
if(err){
console.log(err);
}
res.write(data);
res.end();
})
}
}).listen(obj.port);
return obj;
}
Your index.js file [https://github.com/notJudahRR/Firwe/blob/main/index.js] set path as an object:
const firwe = require("./src/index.js");
let server = firwe({
port: 8080,
path: {
"/": "index.html"
},
});
server.initServer();
Then, in server.js [https://github.com/notJudahRR/Firwe/blob/main/src/server.js] you must handle appropriately:
const http = require("http");
const fs = require("fs");
const type = require("./type.js");
function createServer(obj) {
var i;
obj.port = obj.port || 8080;
obj.path = obj.path || {
"/": "index.html",
};
http
.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/html" });
Object.values(obj.path).forEach((v) => {
fs.readFile(v, "utf-8", (err, data) => {
if (err) {
console.log(err);
}
res.write(data);
res.end();
});
});
})
.listen(obj.port);
return obj;
}
module.exports = createServer;
Object.values loop in each object property value and then you get the index.html to get the file to render.

node server (without Express) does not render image and it keeps loading at localhost

I created a server without express and I'm trying to server a simple static webpage on localhost
here is my code :
const fs = require('fs')
const url = require('url');
const hostname = 'localhost'
const port = 3000;
const path = require ('path');
const http = require ('http')
const server = http.createServer((req, res) => {
if (req.url.match (/.css$/)) {
let cssPath = path.join (__dirname, req.url)
let cssReadStream = fs.createReadStream (cssPath, 'UTF-8')
res.statusCode = 200;
res.setHeader ("Content-Type", "text/css");
cssReadStream.pipe (res)
}
if (req.url === "/") {
fs.readFile("./index.html", 'UTF-8', (err, data) => {
res.statusCode = 200;
res.setHeader("Content-Type", "text/html");
res.end(data);
})
}
if (req.url.match (/.jpg$/)) {
let jpgPath = path.join (req.url)
console.log (jpgPath)
let jpgReadStream = fs.createReadStream (jpgPath, 'UTF-8')
res.statusCode = 200;
res.setHeader ('Content-Type', 'image/jpg')
jpgReadStream.pipe (res)
}
})
server.listen (port, hostname, () => {
console.log ('server start')
})
first of all, it can display the HTML and CSS, however, localhost just keeps on loading after HTML and CSS displayed. Second of All, the image cannot be display (a instagram icon name icon.jpg).
the end result should look something like this:
I guess it has something to do with the favicon thing, but how do i fix it?
you need to use response.send() function which will be used to send the response back
const server = http.createServer((req, res) => {
if (req.url.match (/.css$/)) {
let cssPath = path.join (__dirname, req.url)
let cssReadStream = fs.createReadStream (cssPath, 'UTF-8')
res.statusCode = 200;
res.setHeader ("Content-Type", "text/css");
cssReadStream.pipe (res)
res.send("your data")
}
if (req.url === "/") {
fs.readFile("./index.html", 'UTF-8', (err, data) => {
res.statusCode = 200;
res.setHeader("Content-Type", "text/html");
res.end(data);
res.send("your data")
})
}
if (req.url.match (/.jpg$/)) {
let jpgPath = path.join (req.url)
console.log (jpgPath)
let jpgReadStream = fs.createReadStream (jpgPath, 'UTF-8')
res.statusCode = 200;
res.setHeader ('Content-Type', 'image/jpg')
jpgReadStream.pipe (res)
res.send("your data")
}
})

Node js- not able to define chunk constant

The function activated by the listener on http.incomingMessage is not working properly, it is supposed to define the constant chunk white the submited input but for some reason it remain UNDEFINED.
I dont get any error message but the page wont stop loading after accessing the page.
const http = require('http');
const fs = require('fs');
const server = http.createServer((req, res) => {
const url = req.url;
const method = req.method;
if (url === '/') {
res.write('<html>');
res.write('<head><title>Enter Message</title></head>');
res.write('<body>');
res.write('<form action="/message" method="POST">');
res.write('<input type="text">');
res.write('<input type="submit">');
res.write('</form>');
res.write('</body>');
res.write('</html>');
return res.end();
}
if (url === '/message') {
const body = [];
req.on('data', chunk => {
body.push(chunk);
});
return req.on('end', () => {
const parsedBody = Buffer.concat(body).toString();
const message = parsedBody.split('=')[1];
console.log(parsedBody);
fs.writeFileSync('message.txt', message, err => {
res.statusCode = 302;
res.setHeader('Location', '/');
return res.end();
});
});
}
res.setHeader('Content-Type', 'text/html')
res.write('<html>');
res.write('<head><title>Enter Message</title></head>');
res.write('<body>');
res.write('<p>My page</p>');
res.write('</body>');
res.write('</html>');
res.end();
});
server.listen(8080);
You are not calling the function properly, change your res.end; to res.end();.
In order to finish sending a request you have to invoke the res.end() function

Simple Node.js server without Express - piping HTML files to response

I am trying my hand at making a simple Node.js server without Express and this where I actually learn a bit more about the down and dirty of actually server files and data on requests based on paths request and basic HTTP stuff.
I have this straightforward server like so:
var http = require('http');
const PORT = 6969;
var allRoutes = require('./routes/all');
var server = http.createServer(allRoutes);
server.listen(PORT, function () {
console.log("Server listening on: http://localhost:%s", PORT);
});
and then I have one "middleware" function like so that handles all requests:
var url = require('url');
var fs = require('fs');
var appRootPath = require('app-root-path');
var path = require('path');
function handleRequest(req, res) {
var requestUrl = url.parse(req.url);
var fsPath;
if (requestUrl.pathname === '/') {
fsPath = path.resolve(appRootPath + '/view/index.html');
}
else {
fsPath = path.resolve(appRootPath + '/view/' + requestUrl.pathname);
}
fs.stat(fsPath, function (err, stat) {
if (err) {
console.log('error occurred...' + err);
return end(req, res);
}
try {
if (stat.isFile()) {
res.writeHead(200);
fs.createReadStream(fsPath).pipe(res);
}
else {
res.writeHead(500);
}
}
finally {
end(req, res);
}
});
}
function end(req, res) {
res.end();
}
module.exports = handleRequest;
the problem I am having is that my function doesn't seem to pipe the response to the browser. The browser shows no evidence of the data come from index.html, which is a barebones .html HTML5 file.
I stole the example, and am surprised it's not really working. Anyone have an idea? I know for sure that the fs.stat function is not experiencing an error and then it is streaming the index.html file, it just doesn't seem to be streaming to the right place...
For starters:
if (requestUrl.pathname = '/')
should be:
if (requestUrl.pathname === '/')
Your code was assigning, not comparing.
In addition, the .pipe() is asynchronous, but you are calling res.end() BEFORE it gets to do it's job in your finally{} block which closes the response stream and stops your pipe from doing anything. By default .pipe() will close the write stream by itself, so you don't need the res.end() at all when using .pipe().
You can change the code to this:
var url = require('url');
var fs = require('fs');
var appRootPath = require('app-root-path');
var path = require('path');
function handleRequest(req, res) {
var requestUrl = url.parse(req.url);
var fsPath;
if (requestUrl.pathname === '/') {
fsPath = path.resolve(appRootPath + '/view/index.html');
}
else {
fsPath = path.resolve(appRootPath + '/view/' + requestUrl.pathname);
}
fs.stat(fsPath, function (err, stat) {
if (err) {
console.log('error occurred...' + err);
return end(req, res);
}
try {
if (stat.isFile()) {
res.writeHead(200);
fs.createReadStream(fsPath).pipe(res);
}
else {
res.writeHead(500);
end(req.res);
}
}
catch(e) {
end(req, res);
}
});
}
function end(req, res) {
res.end();
}
module.exports = handleRequest;

Categories

Resources