【问题标题】:Getting raw request alongside body's text in express以快递方式获取原始请求以及正文的文本
【发布时间】:2018-06-24 11:06:39
【问题描述】:

我有一个快速应用程序,它处理这样的发布请求正文:

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 请求示例(取自 here):

POST / HTTP/1.1
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13

say=Hi&to=Mom

当我遇到错误时,我需要这个。

【问题讨论】:

    标签: node.js http express


    【解决方案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 处理程序中检测到错误,我该如何使用它?我不想记录所有请求。只有那些有错误的。
    • 您知道如何从令牌中编写原始请求吗?我不关心响应、错误代码或时间。只是原始请求。
    【解决方案2】:

    您可以使用error-handling middleware

    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 });
    
        });
    
    });
    

    希望对你有帮助

    【讨论】:

    • 感谢您的帖子,但您的回答并没有说明我如何按照原始请求来。这就是我所关心的。没有错误消息,没有响应状态码,只是接收到的纯原始请求。
    • 原始请求是什么意思?
    • 我认为req.originalUrl会返回请求url
    • 原始请求:请求的文本表示形式,包括标头、主机、正文以及在对其进行任何处理之前最初发送到 Web 服务器(此处表示)的任何内容。
    • req对象有很多方法,你可以用req.hostname获取请求主机,req.ip获取ip,req.protocol...这里是@来自文档的 987654322@,提供的答案只是一个示例,您可以在日志文件中存储您想要的任何内容
    【解决方案3】:

    由于对于如何查看原始请求(标头、正文和所有内容)的问题,这里没有任何实际答案,我将投入两分钱。

    简短的回答是:你不能。 Express 不提供该功能,底层节点 http 模块 doesn't either

    更长的答案是:你可以在某种程度上重建它。您可以访问请求的原始标头并将它们重新组合成原始文本。您还可以从套接字读取原始有效负载数据,并将其保存到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') 似乎干扰了后来的中间件......响应永远不会通过
    猜你喜欢
    • 1970-01-01
    • 2022-08-08
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    • 2019-01-07
    • 2013-09-13
    • 1970-01-01
    • 2023-03-25
    相关资源
    最近更新 更多