Node.js原生HTTP服务如何重置请求队列仅校验最新POST请求
问题说明
你遇到的历史请求数据留存、重复校验旧请求的问题,和所谓「request queue重置」没有任何关系,完全是代码逻辑错误导致的,核心bug点如下:
- 存储请求体的
body、存储校验结果的checkNumber被定义为全局变量,所有进入服务的请求共享这两个值,上一次请求的body不会自动清空,新请求传输数据时只会在旧字符串后追加内容,自然会把历史参数都带进来 - 没有监听请求对象的
end事件,请求体还没接收完整就直接解析参数、执行校验;同时质数校验的异步逻辑没有做等待,还没等所有数字校验完成就重置结果、返回响应,会出现返回值和实际校验结果不一致的问题 - 路由判断、请求方法判断的分支逻辑写错,会出现非目标接口也触发逻辑、重复调用
res.end()抛错的问题,原代码路径定义缺失开头的/,实际永远匹配不到目标路由
修复后完整代码
import { createServer } from "http"; import { parse } from "querystring"; import { port } from "./config.js"; const PORT = process.env.PORT || port; const server = createServer(async (req, res) => { res.statusCode = 200; res.setHeader("Content-Type", "text/html"); const FORM_URLENCODED = "application/x-www-form-urlencoded"; const POST_PATH = "/api/numbers/prime/validate"; const GET_PATH = "/api/numbers/prime"; // 每次请求进来重新初始化变量,作用域仅限当前请求,不会残留历史数据 let body = ""; let checkNumber = true; // 仅处理匹配路径、匹配请求头的POST请求 if (req.method === "POST" && req.url === POST_PATH && req.headers["content-type"] === FORM_URLENCODED) { req.on("data", (chunk) => { body += chunk.toString(); }); // 等请求体完全接收完成再执行解析校验 req.on("end", async () => { const params = parse(body); // 等待所有校验逻辑执行完成再拿最终结果 checkNumber = await checkValuesInObject(params); res.end(`${checkNumber}`); }); return; } // 其余非目标请求直接结束响应 res.end(); }); server.listen(PORT, () => { console.log(`listening on port ${PORT}`); }); async function checkIfPrime(number) { const num = Number(number); if (isNaN(num) || num < 2) return false; if (num === 2) return true; if (num % 2 === 0) return false; // 优化质数判断性能,只需循环到数值平方根即可 for (let i = 3; i <= Math.sqrt(num); i += 2) { if (num % i === 0) return false; } return true; } async function checkValuesInObject(obj) { const values = Object.values(obj); for (const value of values) { // 兼容参数为数组的场景 const numList = Array.isArray(value) ? value : [value]; for (const num of numList) { const isPrime = await checkIfPrime(num); if (!isPrime) return false; } } return true; } async function printPrime(number) { let numbers = ""; for (let i = 2; i <= number; i++) { const check = await checkIfPrime(i); if (check) { numbers += i + " "; } } return numbers; }
关键改动说明
- 把
body、checkNumber挪到每个请求的处理函数内部定义,每次新请求进来都会重新初始化空值,从根源上避免历史请求数据残留 - 补全
req.on('end')事件监听,确保请求体完全接收完成后再做参数解析和校验 - 重写校验逻辑的异步处理,直接通过
checkValuesInObject返回最终校验结果,不再靠全局共享变量传递值,彻底解决异步时序导致的结果错乱问题 - 修正了路径前缀缺失的bug,删除了未使用的
inspector模块导入 - 优化了质数判断逻辑的执行效率,增加了非数字、小于2等无效参数的边界判断
内容的提问来源于stack exchange,提问作者Bar
相关产品推荐
相关产品推荐

