Express.js无法将HTTP请求内容作为响应返回的原因及解决方案
报错原因
response.send()接收到对象类型参数时,会默认调用JSON.stringify()做JSON序列化,序列化过程遇到循环引用就会抛出你看到的Converting circular structure to JSON错误。- Express的
request对象是基于Node.js原生IncomingMessage封装的实例,内部持有底层TCP Socket、HTTP解析器等运行时对象,这些对象之间存在互相引用的闭环:比如request.socket指向Socket实例,Socket实例下的parser.socket属性又指回自身,JSON序列化无法处理这种循环结构,就会直接报错。 - 你用
console.log(request)能正常打印,是因为console.log内置了循环引用处理逻辑,遇到循环引用时会自动输出[Circular]标记截断,不会做全量递归序列化,所以不会抛错,和response.send()的处理逻辑完全不同。
实现方案
你不需要把整个request服务端运行时对象全量返回给客户端——这个对象包含大量服务端内部状态、底层连接属性,本身就不应该对外暴露。只需要提取HTTP请求的核心信息返回即可,参考代码如下:
const express = require('express'); const app = express(); const port = 3000; // 注册中间件用于解析JSON格式的请求体 app.use(express.json()); app.get("/", function(request, response){ // 提取请求核心字段,避开带循环引用的内部属性 const requestInfo = { httpMethod: request.method, requestUrl: request.url, requestPath: request.path, queryParams: request.query, requestHeaders: request.headers, requestBody: request.body, clientIp: request.ip }; response.send(requestInfo); }); app.listen(port, function() { console.log("Server started on port #" + port); });
如果是调试场景需要查看完整request对象结构,可以用Node.js内置的util模块将对象转为字符串,自动处理循环引用后再返回:
const express = require('express'); const util = require('util'); const app = express(); const port = 3000; app.get("/", function(request, response){ // depth: null 表示递归打印所有层级,自动处理循环引用 const requestDebugStr = util.inspect(request, { depth: null }); response.type('text/plain').send(requestDebugStr); }); app.listen(port, function() { console.log("Server started on port #" + port); });
内容的提问来源于stack exchange,提问作者Jana
相关产品推荐
相关产品推荐

