here I try to run simple server using nodejs server listen for massage to be posted to "/msg" then it write down the message to entry.txt and redirect user to "/home"
but It get error code: 'ERR_HTTP_HEADERS_SENT'
and stop server while redirecting user witch result in display of This site can’t be reached page
import http from "http";
import fs from "fs";
export default sample_server()
function sample_server() {
const server = http.createServer((req ,res)=>{
const {url , method} = req;
res.setHeader("Content-Type", "text/html");
if(url === "/home"){
res.write("<html>")
res.write("<head><title>page</title></head>")
res.write("<body><center><h1>welcome</h1>")
res.write("<form method='POST' action='/msg'>")
res.write("<input type='text' name='msg'>")
res.write("<input type='submit'>")
res.write("</form></center></body></html>")
return res.end()
}else if(url === "/msg" && method ==="POST"){
res.write("<html>")
res.write("<head><title>page</title></head>")
res.write("<body><center><h1>massage</h1></center></body>")
res.write("</html>")
let msg = [];
req.on("data" , chunk => {
msg.push(chunk)
})
req.on("end" , () => {
msg = Buffer.concat(msg).toString().split("=")[1]
fs.appendFileSync("./files/entry.txt" , `entered: ${msg}\n`)
})
res.writeHead(302, { Location: "/home" })
return res.end()
}else{
res.write("<html>")
res.write("<head><title>page</title></head>")
res.write("<body><center><h1>not found</h1></center></body>")
res.write("</html>")
return res.end()
}
})
server.listen(3030)
}
I wonder if it got anything to do with req.on("data" , () => {...})
or req.on("end" , () => {...})
running async from respons
so far I tried using
res.statusCode = 302;
res.setHeader("Location", "/");
instead of res.writeHead(302, { Location: "/home" });
but I didn't solve the problem
CodePudding user response:
You are trying to write the header AFTER you send the body, but the header needs to be sent before. When you call the first res.write()
, that causes the http library to send the headers (with whatever has been set up to that point). When you then try to do res.writeHead(302, { Location: "/home" })
later, the http engine realizes that the headers have already sent and thus you get the error ERR_HTTP_HEADERS_SENT
because that's literally what the http engine is discovering. You're asking to send headers, but they've already been sent. Obviously, you can't do things in that order.
There's also no point in sending a body to the request when you're sending a redirect (the browser won't display the body anyway so it's just a waste to send the body).
And, as I said in a comment, you should put the res.end()
into the end
event handler so you aren't ending the request until you're done reading the incoming stream.
And, you shouldn't be using synchronous I/O in your http server request handlers because that can ruin the ability of your server to scale. Instead, use asynchronous file I/O.
To fix all four of these, change from this:
res.write("<html>")
res.write("<head><title>page</title></head>")
res.write("<body><center><h1>massage</h1></center></body>")
res.write("</html>")
let msg = [];
req.on("data" , chunk => {
msg.push(chunk)
})
req.on("end" , () => {
msg = Buffer.concat(msg).toString().split("=")[1]
fs.appendFileSync("./files/entry.txt" , `entered: ${msg}\n`)
})
res.writeHead(302, { Location: "/home" })
return res.end()
to this:
res.writeHead(302, { Location: "/home" })
let msg = [];
req.on("data" , chunk => {
msg.push(chunk)
})
req.on("end" , () => {
msg = Buffer.concat(msg).toString().split("=")[1]
fs.appendFile("./files/entry.txt" , `entered: ${msg}\n`, (err) => {
if (err) {
console.log(err);
}
res.end();
});
});