node_request_curl
v2.0.0
Published
NODE 请求转换为curl
Downloads
59
Readme
node_request_curl
🚀 Node.js 中间件库,将 HTTP/HTTPS 请求转换为 curl 命令格式,便于调试和分析
✨ 特性
- 🔍 无侵入式集成 - 作为中间件使用,不影响现有业务逻辑
- 🌍 跨平台兼容 - 支持 Windows 和 POSIX 系统的字符串转义
- ⚡ 高性能设计 - 智能流处理,避免大数据内存占用
- 🛡️ 安全可靠 - 内置数据大小限制和错误降级机制
- 📊 详细日志 - 结构化输出包含时间戳、请求、响应信息
- 🔧 易于调试 - 生成标准 curl 命令,便于问题复现
- 🏗️ 企业级质量 - 完整的错误处理和 JSDoc 文档注释
- ⚙️ 环境变量配置 - 支持通过环境变量自定义配置参数
📦 安装
npm install node_request_curl --save🚀 快速开始
Express 应用集成
const express = require("express");
const recorder = require("node_request_curl");
const app = express();
// 作为中间件使用
app.use(function (req, res, next) {
recorder((record) => {
console.log(`[${record.time}] ${record.request}`);
console.log(record.error || record.response);
});
next();
});
app.listen(3000);Koa 应用集成
const Koa = require("koa");
const recorder = require("node_request_curl");
const app = new Koa();
app.use(async (ctx, next) => {
recorder((record) => {
console.log(`[${record.time}] ${record.request}`);
console.log(record.error || record.response);
});
await next();
});
app.listen(3000);微服务调用监控
const http = require("http");
const recorder = require("node_request_curl");
// 启用请求记录
recorder((record) => {
// 记录到日志系统
logger.info("HTTP Request", {
timestamp: record.time,
curl: record.request,
response: record.response,
error: record.error,
});
});
// 正常进行 HTTP 请求
const req = http.request("http://api.example.com/users", (res) => {
// 处理响应
});
req.end();📖 API 参考
recorder(callbackOrOptions, [callback])
HTTP/HTTPS 请求记录器的主要函数,支持两种调用方式:
方式一:直接传入回调函数
const recorder = require("node_request_curl");
recorder((record) => {
console.log(`[${record.time}] ${record.request}`);
console.log(record.error || record.response);
});方式二:传入配置对象
const recorder = require("node_request_curl");
recorder(
{
lengthLimit: 5120, // 响应体大小限制
requestBodyLimit: 4096, // 请求体大小限制
responseSizeExceededMessage: "响应数据过大", // 响应过大占位符
defaultEncoding: "utf8", // 默认字符编码
},
(record) => {
console.log(`[${record.time}] ${record.request}`);
console.log(record.error || record.response);
}
);参数说明
callbackOrOptions
类型: Function | Object
当为 Function 时,直接作为记录完成后的回调函数。
当为 Object 时,作为配置选项对象,支持以下属性:
| 属性名 | 类型 | 默认值 | 说明 |
| ----------------------------- | -------- | ----------------------------- | -------------------------------------------------------- |
| lengthLimit | number | 3072 | 响应体大小限制(字节),超过此限制时使用占位符替代 |
| requestBodyLimit | number | 2048 | 请求体大小限制(字节),超过此限制时不包含在 curl 命令中 |
| responseSizeExceededMessage | string | "the response is too large" | 响应体过大时的占位符文本 |
| defaultEncoding | string | "utf8" | 默认字符编码 |
callback
类型: Function
必需: 当第一个参数为配置对象时必需
记录完成后的回调函数,接收一个 record 对象作为参数。
配置优先级
配置参数的优先级从高到低为:
- 函数参数配置 - 通过
recorder()函数传入的配置对象 - 环境变量配置 - 通过环境变量设置的值
- 默认值 - 代码中定义的默认值
环境变量映射
| 函数参数 | 环境变量 | 默认值 |
| ----------------------------- | ---------------------------------- | ----------------------------- |
| lengthLimit | NODE_REQUEST_CURL_RESPONSE_LIMIT | 3072 |
| requestBodyLimit | NODE_REQUEST_CURL_REQUEST_LIMIT | 2048 |
| responseSizeExceededMessage | NODE_REQUEST_CURL_SIZE_MESSAGE | "the response is too large" |
| defaultEncoding | NODE_REQUEST_CURL_ENCODING | "utf8" |
使用示例
基础用法
const recorder = require("node_request_curl");
// 使用默认配置
recorder((record) => {
console.log("Request:", record.request);
console.log("Response:", record.response);
if (record.error) {
console.error("Error:", record.error);
}
});自定义配置
const recorder = require("node_request_curl");
// 自定义配置
recorder(
{
lengthLimit: 1024, // 限制响应体为 1KB
requestBodyLimit: 512, // 限制请求体为 512 字节
responseSizeExceededMessage: "[数据过大]", // 中文占位符
defaultEncoding: "utf8",
},
(record) => {
console.log(`时间: ${record.time}`);
console.log(`请求: ${record.request}`);
console.log(`响应: ${record.response}`);
}
);结合环境变量
# 设置环境变量
export NODE_REQUEST_CURL_RESPONSE_LIMIT=5120
export NODE_REQUEST_CURL_REQUEST_LIMIT=4096
export NODE_REQUEST_CURL_SIZE_MESSAGE="响应数据过大"
export NODE_REQUEST_CURL_ENCODING="utf8"// 环境变量会自动生效
recorder((record) => {
// 使用环境变量配置的限制
logger.info("HTTP Request", record);
});
// 函数参数配置会覆盖环境变量
recorder(
{
lengthLimit: 8192, // 这会覆盖环境变量的设置
},
(record) => {
logger.info("HTTP Request", record);
}
);📋 输出格式
记录回调函数会接收一个包含以下字段的对象:
{
time: Date, // 请求时间戳
request: String, // 等效的 curl 命令
response: String, // 响应状态行、头部和正文
error: String // 错误信息 (如果有)
}示例输出
# 请求 curl 命令
curl 'https://api.github.com/user' -H 'Authorization: token ghp_xxxx' -H 'User-Agent: MyApp/1.0' --compressed
# 响应信息
HTTPS/1.1 200 OK
server: GitHub.com
content-type: application/json; charset=utf-8
x-ratelimit-limit: 5000
{"login":"username","id":12345,"avatar_url":"https://..."}⚙️ 高级配置
环境变量支持
本库支持通过环境变量进行灵活配置:
# 响应体大小限制 (默认: 3072 字节)
NODE_REQUEST_CURL_RESPONSE_LIMIT=5120
# 请求体大小限制 (默认: 2048 字节)
NODE_REQUEST_CURL_REQUEST_LIMIT=4096
# 响应体过大时的占位符文本
NODE_REQUEST_CURL_SIZE_MESSAGE="响应数据过大"
# 默认字符编码 (默认: utf8)
NODE_REQUEST_CURL_ENCODING=utf8
# 忽略 SSL 证书验证 (开发环境)
NODE_TLS_REJECT_UNAUTHORIZED=0
# 启动应用
node app.js条件启用记录
const recorder = require("node_request_curl");
// 仅在开发环境启用
if (process.env.NODE_ENV === "development") {
recorder((record) => {
console.log(record.request);
});
}自定义日志处理
const fs = require("fs");
const recorder = require("node_request_curl");
recorder((record) => {
// 写入文件日志
const logEntry = {
timestamp: record.time.toISOString(),
method: extractMethod(record.request),
url: extractUrl(record.request),
status: extractStatus(record.response),
error: record.error,
};
fs.appendFileSync("http-requests.log", JSON.stringify(logEntry) + "\n");
});🔧 技术实现
核心架构
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ HTTP 请求 │───▶│ httpRecorder │───▶│ requestToCurl │
│ (http/https) │ │ (请求拦截) │ │ (命令生成) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│
▼
┌──────────────────┐
│ NewReadable │
│ (流包装器) │
└──────────────────┘关键特性
- 代理模式: 通过
http.__request__保存原始方法,避免循环调用 - 流处理: 使用
NewReadable包装响应流,支持多消费者 - 跨平台: 自动检测操作系统,使用对应的字符串转义策略
- 性能优化: 响应体 > 3KB 时使用占位符,请求体 > 2KB 时不包含在 curl 中
- 错误处理: 多层级错误处理机制,确保系统稳定性
- 模块化设计: 9 个专门函数,职责分离,便于维护和测试
🆕 最新优化 (v1.8.0)
代码质量提升
- ✅ 完整重构: 从单一函数重构为模块化设计 (9 个专门函数)
- ✅ JSDoc 文档: 添加 340+ 行详细的 JSDoc 注释
- ✅ TypeScript 类型: 完整的类型定义和参数验证
- ✅ ESLint 检查: 通过严格的代码质量检查,零错误零警告
错误处理增强
- 🛡️ 多层级保护: 请求错误、响应错误、回调错误的全面处理
- 🛡️ 降级机制: 出错时提供有意义的错误信息,而不是崩溃
- 🛡️ 异步处理: 使用
setImmediate()避免阻塞主线程 - 🛡️ 状态管理: 防止重复事件处理和内存泄漏
性能优化
- ⚡ 配置化常量: 使用环境变量替代硬编码值
- ⚡ 内存安全: 智能流处理,避免大数据内存占用
- ⚡ 事件优化: 优化事件监听器,防止内存泄漏
- ⚡ 异步回调: 非阻塞的错误处理和回调机制
📊 性能考虑
内存管理
- ✅ 响应体超过 3KB 时自动截断 (可配置)
- ✅ 请求体超过 2KB 时不包含在 curl 命令中 (可配置)
- ✅ 使用流式处理,避免大数据一次性加载
- ✅ 智能事件监听器管理,防止内存泄漏
生产环境建议
// 生产环境优化配置
const recorder = require("node_request_curl");
if (process.env.ENABLE_REQUEST_LOGGING === "true") {
recorder((record) => {
// 异步写入,避免阻塞主线程
setImmediate(() => {
// 只记录关键信息,减少内存占用
logger.debug("HTTP Request", {
curl: record.request,
status: extractStatus(record.response),
timestamp: record.time,
hasError: !!record.error,
});
});
});
}配置优化示例
# 生产环境配置
NODE_REQUEST_CURL_RESPONSE_LIMIT=1024 # 减少响应体限制
NODE_REQUEST_CURL_REQUEST_LIMIT=512 # 减少请求体限制
NODE_REQUEST_CURL_SIZE_MESSAGE="[数据过大]" # 简化占位符🔍 故障排查
常见问题
1. 内存使用过高
// 检查是否有大量请求未正确处理
recorder((record) => {
if (record.response.includes("the response is too large")) {
console.warn("Large response detected, consider optimizing API");
}
});2. 跨平台兼容性问题
// 验证生成的 curl 命令
recorder((record) => {
const platform = require("os").platform();
console.log(`Platform: ${platform}, Curl: ${record.request}`);
});3. SSL 证书问题
# 临时忽略 SSL 验证 (仅开发环境)
NODE_TLS_REJECT_UNAUTHORIZED=0 npm start4. 错误处理验证
// 验证错误处理机制
recorder((record) => {
if (record.error) {
const errorObj = JSON.parse(record.error);
console.error("Request failed:", {
message: errorObj.message,
code: errorObj.code,
curl: record.request,
});
}
});🧪 测试
# 运行代码检查
npm run lint
# 提交前检查 (自动触发)
npm run precommit
# 检查特定文件
npx eslint src/httpRecorder/httprecorder.js --fix📚 使用场景
1. API 开发调试
// 记录所有外部 API 调用
recorder((record) => {
if (record.request.includes("api.external.com")) {
console.log("External API Call:", record.request);
// 检查响应状态
if (record.error) {
console.error("API调用失败:", JSON.parse(record.error));
}
}
});2. 微服务监控
// 服务间调用追踪
recorder((record) => {
const serviceCall = {
service: extractService(record.request),
timestamp: record.time,
curl: record.request,
success: !record.error,
responseSize: record.response.length,
};
metrics.increment("service.calls", 1, {
service: serviceCall.service,
success: serviceCall.success,
});
});3. 生产问题排查
// 错误请求记录
recorder((record) => {
if (record.error || record.response.includes("500")) {
errorLogger.error("Failed HTTP Request", {
curl: record.request,
error: record.error,
response: record.response.substring(0, 500), // 限制日志大小
timestamp: record.time.toISOString(),
});
}
});4. 性能监控
// 请求性能分析
const startTimes = new Map();
recorder((record) => {
const requestId = generateRequestId(record.request);
// 记录响应时间和大小
performanceLogger.info("HTTP Performance", {
requestId,
curl: record.request,
responseSize: record.response.length,
hasError: !!record.error,
timestamp: record.time,
});
});🤝 贡献
我们欢迎所有形式的贡献!
开发流程
- Fork 本仓库
- 创建特性分支:
git checkout -b feature/amazing-feature - 提交更改:
git commit -m 'feat: add amazing feature' - 推送分支:
git push origin feature/amazing-feature - 提交 Pull Request
代码规范
- 使用 2 个空格缩进
- 遵循 ESLint 配置
- 提交信息遵循 Conventional Commits
- 使用
npm run lint检查代码风格 - 添加完整的 JSDoc 文档注释
- 确保所有函数都有适当的错误处理
开发指南
# 克隆项目
git clone https://github.com/ryansecret/nodeRequestCurl.git
cd nodeRequestCurl
# 安装依赖
npm install
# 代码检查
npm run lint
# 提交代码 (会自动运行 precommit 检查)
git add .
git commit -m "feat: your feature description"📄 许可证
🔗 相关链接
📈 版本历史
v1.8.0 (最新)
- 🔥 重大重构: 完全重写 httprecorder.js,提升代码质量
- ✨ 新增: 完整的 JSDoc 文档注释和类型定义
- 🛡️ 增强: 多层级错误处理机制
- ⚙️ 配置: 支持环境变量配置所有参数
- 🚀 性能: 优化内存使用和事件处理
- 🧪 质量: 通过严格的 ESLint 检查
v1.7.1 (稳定版)
- 🐛 修复若干已知问题
- 📚 更新文档
� 致谢
感谢所有贡献者对本项目的支持!
特别感谢:
- 所有提交 Issue 和 PR 的开发者
- 在生产环境中使用并提供反馈的用户
- 开源社区的支持和建议
如果这个项目对你有帮助,请给它一个 ⭐️!
