“code: ‘ERR_HTTP_HEADERS_SENT'” 在重定向时出现错误。

huangapple go评论139阅读模式
英文:

getitng "code: 'ERR_HTTP_HEADERS_SENT'" error while redirecting

问题

在尝试使用Node.js运行简单服务器时,我监听消息是否发布到"/msg",然后将消息写入entry.txt并将用户重定向到"/home"。但是,我遇到了错误code: 'ERR_HTTP_HEADERS_SENT',并在重定向用户时停止了服务器,导致显示无法访问此网站页面。

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)
}

我想知道是否与req.on("data", () => {...})req.on("end", () => {...})从响应中异步运行有关。

到目前为止,我尝试使用以下代码替代res.writeHead(302, { Location: "/home" });

res.statusCode = 302;
res.setHeader("Location", "/");

但是这并没有解决问题。

英文:

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: &#39;ERR_HTTP_HEADERS_SENT&#39; and stop server while redirecting user witch result in display of This site can’t be reached page

import http from &quot;http&quot;;
import fs from &quot;fs&quot;;
export default sample_server()
function sample_server() {
const server =  http.createServer((req ,res)=&gt;{
const {url , method} = req;
res.setHeader(&quot;Content-Type&quot;, &quot;text/html&quot;);
if(url === &quot;/home&quot;){
res.write(&quot;&lt;html&gt;&quot;)
res.write(&quot;&lt;head&gt;&lt;title&gt;page&lt;/title&gt;&lt;/head&gt;&quot;)
res.write(&quot;&lt;body&gt;&lt;center&gt;&lt;h1&gt;welcome&lt;/h1&gt;&quot;)
res.write(&quot;&lt;form method=&#39;POST&#39; action=&#39;/msg&#39;&gt;&quot;)
res.write(&quot;&lt;input type=&#39;text&#39; name=&#39;msg&#39;&gt;&quot;)
res.write(&quot;&lt;input type=&#39;submit&#39;&gt;&quot;)
res.write(&quot;&lt;/form&gt;&lt;/center&gt;&lt;/body&gt;&lt;/html&gt;&quot;)
return  res.end()
}else if(url === &quot;/msg&quot; &amp;&amp; method ===&quot;POST&quot;){
res.write(&quot;&lt;html&gt;&quot;)
res.write(&quot;&lt;head&gt;&lt;title&gt;page&lt;/title&gt;&lt;/head&gt;&quot;)
res.write(&quot;&lt;body&gt;&lt;center&gt;&lt;h1&gt;massage&lt;/h1&gt;&lt;/center&gt;&lt;/body&gt;&quot;)
res.write(&quot;&lt;/html&gt;&quot;)
let msg = [];
req.on(&quot;data&quot;  , chunk =&gt; {
msg.push(chunk)
})
req.on(&quot;end&quot;  , () =&gt; {
msg = Buffer.concat(msg).toString().split(&quot;=&quot;)[1]
fs.appendFileSync(&quot;./files/entry.txt&quot; , `entered: ${msg}\n`)
})
res.writeHead(302, { Location: &quot;/home&quot; })
return  res.end()
}else{
res.write(&quot;&lt;html&gt;&quot;)
res.write(&quot;&lt;head&gt;&lt;title&gt;page&lt;/title&gt;&lt;/head&gt;&quot;)
res.write(&quot;&lt;body&gt;&lt;center&gt;&lt;h1&gt;not found&lt;/h1&gt;&lt;/center&gt;&lt;/body&gt;&quot;)
res.write(&quot;&lt;/html&gt;&quot;)
return  res.end()
}
})
server.listen(3030)
}

I wonder if it got anything to do with req.on(&quot;data&quot; , () =&gt; {...}) or req.on(&quot;end&quot; , () =&gt; {...}) running async from respons

so far I tried using

res.statusCode = 302;
res.setHeader(&quot;Location&quot;, &quot;/&quot;);

instead of res.writeHead(302, { Location: &quot;/home&quot; }); but I didn't solve the problem

答案1

得分: 0

你正在尝试在发送正文之后编写标头,但标头需要在正文之前发送。当你调用第一个 res.write() 时,这会导致 http 库发送标头(包括到那时设置的内容)。然后当你尝试稍后执行 res.writeHead(302, { Location: &quot;/home&quot; }) 时,http 引擎意识到标头已经发送,因此你会收到错误 ERR_HTTP_HEADERS_SENT,因为这就是 http 引擎正在发现的内容。你要求发送标头,但它们已经发送了。显然,你不能按照这个顺序执行操作。

当你发送重定向时,没有必要发送请求正文(浏览器不会显示正文,所以发送正文只是浪费资源)。

另外,正如我在评论中所说,你应该将 res.end() 放入 end 事件处理程序中,这样在完成读取输入流之前不会结束请求。

此外,在你的 http 服务器请求处理程序中不应该使用同步 I/O,因为这可能会破坏服务器扩展的能力。相反,使用异步文件 I/O。

要解决这四个问题,将代码从以下内容更改为以下内容:

res.writeHead(302, { Location: &quot;/home&quot; })
let msg = [];
req.on(&quot;data&quot;  , chunk =&gt; {
    msg.push(chunk)
})
req.on(&quot;end&quot;  , () =&gt; {
    msg = Buffer.concat(msg).toString().split(&quot;=&quot;)[1]
    fs.appendFile(&quot;./files/entry.txt&quot; , `entered: ${msg}\n`, (err) =&gt; {
        if (err) {
            console.log(err);
        }
        res.end();
    });
});

这将解决你的问题。

英文:

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: &quot;/home&quot; }) 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(&quot;&lt;html&gt;&quot;)
res.write(&quot;&lt;head&gt;&lt;title&gt;page&lt;/title&gt;&lt;/head&gt;&quot;)
res.write(&quot;&lt;body&gt;&lt;center&gt;&lt;h1&gt;massage&lt;/h1&gt;&lt;/center&gt;&lt;/body&gt;&quot;)
res.write(&quot;&lt;/html&gt;&quot;)
let msg = [];
req.on(&quot;data&quot;  , chunk =&gt; {
msg.push(chunk)
})
req.on(&quot;end&quot;  , () =&gt; {
msg = Buffer.concat(msg).toString().split(&quot;=&quot;)[1]
fs.appendFileSync(&quot;./files/entry.txt&quot; , `entered: ${msg}\n`)
})
res.writeHead(302, { Location: &quot;/home&quot; })
return  res.end()

to this:

        res.writeHead(302, { Location: &quot;/home&quot; })
let msg = [];
req.on(&quot;data&quot;  , chunk =&gt; {
msg.push(chunk)
})
req.on(&quot;end&quot;  , () =&gt; {
msg = Buffer.concat(msg).toString().split(&quot;=&quot;)[1]
fs.appendFile(&quot;./files/entry.txt&quot; , `entered: ${msg}\n`, (err) =&gt; {
if (err) {
console.log(err);
}
res.end();
});
});

huangapple
  • 本文由 发表于 2023年1月9日 04:29:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051050.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定