请求服务器时出现net::ERR_CONNECTION_CLOSED错误的修复方案
修复登录请求的net::ERR_CONNECTION_CLOSED错误
问题背景
搭建了非安全聚焦的简易登录界面服务端与客户端,客户端发送请求时触发net::ERR_CONNECTION_CLOSED错误。相关代码及现象如下:
服务端代码(src/index.mjs)
import { createServer } from "http"; const hostname = "127.0.0.1"; const port = 1337; const server = createServer((req, res) => { if (req.method === "GET" && req.url === "/login") { const { username, password } = req.query; console.log("usr:" + username + "pass:" + password); // Perform authentication logic here if ( username === "read_password" && password === "security_isnt_what_i_want" ) { // Authentication successful res.statusCode = 200; res.setHeader("Content-Type", "text/plain"); res.end("Login successful"); } else { // Authentication failed res.statusCode = 401; res.setHeader("Content-Type", "text/plain"); res.end("Login failed"); } } else { // Handle other requests res.statusCode = 404; res.setHeader("Content-Type", "text/plain"); res.end("Not Found"); } }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
客户端代码(index.html)
<!DOCTYPE html> <body> <script> let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { console.log(this.responseText); } }; let loginForm = ` <form> <label>Username: </label> <input type="text" name="username" /> <label>Password: </label> <input type="password" name="password" /> <input type="submit" value="Login" /> </form> `; let loginDiv = document.createElement("div"); loginDiv.innerHTML = loginForm; document.body.appendChild(loginDiv); document.querySelector("form").addEventListener("submit", (e) => { e.preventDefault(); let username = document.querySelector('input[name="username"]').value; let password = document.querySelector('input[name="password"]').value; xhr.open("POST", "https://127.0.0.1:1337/login", true); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.send("username=" + username + "&password=" + password); }); </script> </body>
现象
- 预期:输入正确用户名(read_password)和密码(security_isnt_what_i_want)后,开发者控制台无错误输出
- 实际:触发
POST https://127.0.0.1:1337/login net::ERR_CONNECTION_CLOSED错误
错误原因
- 协议不匹配:服务端是HTTP服务,客户端却用HTTPS发起请求,导致连接无法建立
- 请求方法不匹配:服务端仅处理
GET方法的/login请求,但客户端发送的是POST请求,服务端无对应处理逻辑,直接返回404或导致连接异常关闭 - 服务端未正确解析请求参数:即使改为GET请求,原生HTTP模块不会自动解析URL查询参数,
req.query会是undefined;POST请求的表单数据也未做解析处理
修复步骤
1. 修复客户端请求
将请求协议从https改为http,与服务端一致:
// 原代码 xhr.open("POST", "https://127.0.0.1:1337/login", true); // 修改后 xhr.open("POST", "http://127.0.0.1:1337/login", true);
2. 修复服务端逻辑
修改服务端以支持POST请求,并解析表单数据:
import { createServer } from "http"; import { parse } from "querystring"; // 引入querystring模块解析表单数据 const hostname = "127.0.0.1"; const port = 1337; const server = createServer((req, res) => { // 统一处理GET和POST的/login请求 if (req.url === "/login") { let params = {}; if (req.method === "GET") { // 解析GET请求的URL参数 const url = new URL(req.url, `http://${hostname}:${port}`); params.username = url.searchParams.get("username"); params.password = url.searchParams.get("password"); handleAuth(params, res); } else if (req.method === "POST") { // 解析POST请求的表单数据 let body = ""; req.on("data", chunk => { body += chunk.toString(); }); req.on("end", () => { params = parse(body); handleAuth(params, res); }); return; // 等待数据接收完成再处理,提前返回避免执行后续逻辑 } } else { res.statusCode = 404; res.setHeader("Content-Type", "text/plain"); res.end("Not Found"); } }); // 提取认证逻辑为单独函数 function handleAuth(params, res) { const { username, password } = params; console.log(`usr:${username} pass:${password}`); if (username === "read_password" && password === "security_isnt_what_i_want") { res.statusCode = 200; res.setHeader("Content-Type", "text/plain"); res.end("Login successful"); } else { res.statusCode = 401; res.setHeader("Content-Type", "text/plain"); res.end("Login failed"); } } server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
3. 可选:完善客户端错误处理
添加错误状态的监听,方便调试:
xhr.onreadystatechange = function () { if (this.readyState == 4) { if (this.status == 200) { console.log(this.responseText); } else { console.log(`登录失败,状态码:${this.status},响应:${this.responseText}`); } } };
内容的提问来源于stack exchange,提问作者WinwinTheDumbguy
相关产品推荐
相关产品推荐

