http.createServer() 创建服务器实例后必须调用 .listen() 绑定端口,否则静默退出;req/res 是原生对象,需手动处理路径解析、响应头、res.end()、POST 数据流及错误捕获。

用 http.createServer() 启动最简服务
Node.js 的 http 模块自带,不用装包,直接 require('http') 就能用。核心是 http.createServer(),它返回一个服务器实例,调用 .listen() 才真正绑定端口。
常见错误:只调了 createServer() 没调 .listen(),程序静默退出,浏览器访问超时;或者端口被占用,报错 Error: listen EADDRINUSE。
-
createServer()的回调函数接收两个参数:req(http.IncomingMessage)和res(http.ServerResponse),不是 Express 那套req/res,没req.query、没res.json() - 必须手动设置响应头,比如
res.writeHead(200, {'Content-Type': 'text/plain'}),否则浏览器可能乱码或下载文件 - 必须显式调用
res.end(),哪怕只写res.end('ok'),漏掉会导致连接挂起、请求卡死
读取 URL 路径和查询参数得自己解析
req.url 是原始字符串,比如 /user?id=123,不自动拆解。想拿到路径或参数,得靠 url.parse() 或更现代的 new URL()。
容易踩坑:直接用 req.url.split('?')[0] 处理路径,遇到带 %20 或中文会出错;或者用 querystring.parse() 解析但没做 req.setEncoding('utf8'),导致 Buffer 乱码。
- 推荐用
new URL(req.url, 'http://localhost'),兼容性好,自动解码,url.pathname和url.searchParams.get('id')直接可用 - 如果用
url.parse(req.url, true),第二个参数true表示自动解析query成对象,但注意 Node 15+ 已废弃该方法 - 别在
req上监听'data'事件前就调res.end(),POST 请求体还没读完就关响应,客户端收不到完整结果
处理 POST 数据要手动拼接 chunk
req 是个可读流,POST 的 body 默认以 Buffer 分块传来,不会自动聚合。不处理,req.body 这种东西根本不存在。
典型现象:表单提交后,服务端打印 req.body 是 undefined,或者只拿到第一段 Buffer。
- 必须监听
'data'事件收集所有chunk,再监听'end'事件做后续处理 - 记得先调
req.setEncoding('utf8'),否则拼出来的可能是乱码字符串;或者统一用Buffer.concat(chunks)再.toString() - 没限制上传大小,大文件可能撑爆内存;生产环境务必加长度判断,比如累计超过 1MB 就
req.destroy()并返回 413
错误没捕获会导致整个进程退出
http 服务器本身不捕获路由逻辑里的异常。比如在 createServer 回调里 JSON.parse('invalid') 抛错,Node 进程直接崩,服务中断。
这和 Express 不同——Express 有顶层错误中间件兜底,原生 http 没这个机制。
- 所有可能抛错的操作(JSON 解析、文件读写、数据库查询)都得包
try/catch - 给
res发送错误响应前,先检查res.headersSent,避免重复writeHead报Error [ERR_HTTP_HEADERS_SENT] - 监听服务器的
'clientError'事件,捕获底层连接错误(如 TLS 握手失败),否则这类错误也会让进程退出
原生 http 模块干净轻量,但每个细节都要亲手托住。路径解析、body 处理、错误边界、编码设置——少一步,线上就可能表现成“偶尔打不开”或“POST 总是失败”。

















