在Express中获取请求正文和原始请求

4
我有一个使用Express框架的应用程序,处理POST请求时会涉及到以下请求体:
var app = express();
app.use(bodyParser.text({ type: "*/*" }));

app.post(url, function(req, res) {
    //Process req.body, handle the errors along the way;
});

现在如果发生错误,我希望能够记录整个请求。我的意思是记录头部、正文和所有内容。就像你使用wireshark查看请求一样。
有人知道最简单的方法吗?
这里有一个HTTP POST请求的示例(取自此处):
POST / HTTP/1.1
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13

say=Hi&to=Mom

我遇到错误时需要这个。
3个回答

4

由于这里没有任何关于如何查看原始请求(头部、正文等)的答案,因此我也想发表一下自己看法。

简短的回答是:你不能。Express不提供此功能,底层的Node http模块也不提供

较长的回答是:你可以在一定程度上重构它。你可以访问请求的原始标头并将它们重新组合成原始文本。你还可以从套接字中读取原始有效负载数据,将其保存到req的属性中,然后在数据发送后使用它。这可能无法获取确切的传入消息,但可以接近。您可以在一个中间件中执行此操作:

server.use((req, res, next) => {
    let data = '';
    req.on('data', (chunk) => {
        data += chunk;
    });
    req.on('end', () => {
        req.rawBody = data;
        let headers = [`${req.method} ${req.url} HTTP/${req.httpVersion}`];
        for (let i = 0; i < req.rawHeaders.length; i += 2) {
            headers.push(`${req.rawHeaders[i]}: ${req.rawHeaders[i + 1]}`);
        }
        req.rawRequest = `${headers.join('\r\n')}\r\n\r\n${req.rawBody}`;
        console.log(`Socket received data:\n\n${req.rawRequest}`);
    });
    next();
});

对我来说,似乎 req.on('data') 会干扰后面的中间件...响应永远不会通过。 - Andy

1

Express有一个很棒的中间件用于记录请求,叫做morgan
你可以定义自己的自定义日志格式

var morgan = require('morgan')
morgan(function (tokens, req, res) {
  return [
    tokens.method(req, res),
    tokens.url(req, res),
    tokens.status(req, res),
    tokens.res(req, res, 'content-length'), '-',
    tokens['response-time'](req, res), 'ms'
  ].join(' ')
})

它有一个“skip”选项用于跳过日志记录,您必须设计自己的策略来跳过或保留日志记录,例如您可以检查响应状态。
var morgan = require('morgan')
morgan(function (tokens, req, res) {
  return [
    tokens.method(req, res),
    tokens.url(req, res),
    tokens.status(req, res),
    tokens.res(req, res, 'content-length'), '-',
    tokens['response-time'](req, res), 'ms'
  ].join(' ')
}, {
     skip: function (req, res) { return res.statusCode == 200 }
})

如果我能在post处理程序中检测到错误,我该如何使用它?我不想记录所有请求,只记录一些出现错误的请求。 - Mehran
你知道如何从令牌中组合原始请求吗?我不关心响应、错误代码或时间。只需要原始请求。 - Mehran

0

您可以使用错误处理中间件

app.use(function(err, req, res, next) {

    // define log format, for example:
    let data = `URL: ${req.originalUrl} - method: ${req.method} - error: ${err.message}`;

    // append to log file
    fs.appendFile('server.log', data, function (err) {

        if (err) throw err;

        // terminate the request/response cycle
        res.status(err.status || 500);
        res.json({ error: err });

    });

});

通过调用next(err)跳转到错误处理中间件,例如:

app.get('some/route', function (req, res, next) {

    someFunction( req.body, function (err) {

        // pass err object to the error middleware
        if (err) return next(err);

        return res.json({ success: true });

    });

});

希望这能有所帮助


谢谢您的帖子,但您的答案并没有说明我如何获取原始请求。这就是我关心的全部。没有错误消息,没有响应状态码,只有纯粹的原始接收请求。 - Mehran
原始请求是什么意思? - YouneL
我认为 req.originalUrl 将返回请求的 URL。 - YouneL
原始请求的文本表示,包括标头、主机、正文以及在对其进行任何处理之前最初发送到Web服务器(在此处为Express)的内容。 - Mehran
req对象有很多方法,例如您可以使用req.hostname获取请求主机,req.ip获取IP,req.protocol...这里是文档的链接,提供的答案只是一个示例,您可以将任何想要的内容存储在日志文件中。 - YouneL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接