Express Morgan日志器:如何记录未转义的查询字符串?
如何用Morgan记录未转义的查询字符串
绝对可以!Morgan的灵活性很强,你完全可以通过自定义日志token来实现记录未转义(或解码后)的查询字符串。下面是几种实用的方案:
方案1:直接截取原始查询字符串
Express的req.url(或req.originalUrl)保留了请求的原始URL,包括服务器接收到的编码后的查询字符串。我们可以自定义一个token来提取这部分内容:
const express = require('express'); const morgan = require('morgan'); const app = express(); // 自定义token:获取原始查询字符串(含?前缀) morgan.token('raw-query', (req) => { const queryStartIndex = req.url.indexOf('?'); return queryStartIndex !== -1 ? req.url.slice(queryStartIndex) : ''; }); // 用自定义token构建日志格式 app.use(morgan(':method :url :raw-query :status :response-time ms')); // 测试路由 app.get('/demo', (req, res) => res.send('Success!')); app.listen(3000);
当发起请求http://localhost:3000/demo?name=John%20Doe&tag=dev%23123时,日志会输出:
GET /demo?name=John%20Doe&tag=dev%23123 ?name=John%20Doe&tag=dev%23123 200 1.234 ms
方案2:记录解码后的可读查询字符串
如果你的需求是把编码字符(比如%20转空格、%23转#)显示为人类可读的格式,可以在自定义token里用decodeURIComponent解码:
// 自定义token:获取解码后的查询字符串 morgan.token('decoded-query', (req) => { const queryStartIndex = req.url.indexOf('?'); if (queryStartIndex === -1) return ''; const encodedQuery = req.url.slice(queryStartIndex); return decodeURIComponent(encodedQuery); }); // 用引号包裹查询字符串,避免特殊字符干扰日志格式 app.use(morgan(':method :url "%decoded-query" :status :response-time ms'));
同样的请求,日志会输出:
GET /demo?name=John%20Doe&tag=dev%23123 "?name=John Doe&tag=dev#123" 200 1.567 ms
方案3:直接记录完整未转义URL
如果不需要拆分查询字符串,想直接记录整个原始URL,可以用req.originalUrl自定义token:
morgan.token('raw-full-url', (req) => req.originalUrl); app.use(morgan(':method :raw-full-url :status :response-time ms'));
日志会直接输出完整的原始请求URL:
GET /demo?name=John%20Doe&tag=dev%23123 200 1.123 ms
注意事项
- 如果查询字符串包含空格、引号等特殊字符,解码后可能干扰日志格式解析,建议用引号包裹查询字符串部分(如方案2所示)。
req.url可能被部分中间件修改,req.originalUrl始终保留请求的原始URL,可靠性更高。
内容的提问来源于stack exchange,提问作者Alexander Mills
相关产品推荐
相关产品推荐

