【问题标题】:How to avoid the data of request stream loss after doing some authentication on node.js?在node.js上做一些认证后如何避免请求流丢失的数据?
【发布时间】:2012-11-04 22:00:09
【问题描述】:

请求流如何与 node.js(express 或 restify)一起工作?

当客户端尝试将音频、mpeg 或其他二进制文件上传到服务器时,请求应该是服务器上的可读流。我们可以使用request.pipe() 管道到另一个流,例如从请求中获取文件,然后使用 knox 将文件上传到 amazon s3。

当我使用异步身份验证方法时,部分流数据会丢失,并且长度与传输的 content-length 标头不再匹配。有什么办法可以避免这种行为? 请求流的数据是仅存储在内存中还是 node.js 将数据存储在某个本地临时文件夹中?

var express = require('express'),
app = express(),
passport = require('passport'),
BasicStrategy = require('passport-http').BasicStrategy;

var users = [
    { id: 1, username: 'bob', password: 'secret', email: 'bob@example.com' }
    , { id: 2, username: 'joe', password: 'birthday', email: 'joe@example.com' }
];

function findByUsername(username, fn) {
    for (var i = 0, len = users.length; i < len; i++) {
        var user = users[i];
        if (user.username === username) {
            return fn(null, user);
        }
    }
    return fn(null, null);
}

passport.use(new BasicStrategy(
    function(username, password, done) {
        process.nextTick(function () {
            findByUsername(username, function(err, user) {
                if (err) { return done(err); }
                if (!user) { return done(null, false); }
                if (user.password != password) { return done(null, false); }
                return done(null, user);
            })
        });
    }));

app.configure(function() {
    app.use(express.logger());
    app.use(passport.initialize());
    app.use(app.router);
});    

app.post('/upload', 
    passport.authenticate('basic', { session: false }),
    function(req, res, next) {

        var dataLength = 0;

        req.on('data', function(chunk) {
            console.log('loading');
            dataLength += chunk.length;

        }).on('end', function() {
            console.log('load end');
            console.log('contentLength: %s', req.headers['content-length']);
            console.log('dataLength:  : %s', dataLength);
            res.send(200);

        }); 
    });

app.listen(8080, function() {
    console.log('server is running');
});

【问题讨论】:

    标签: node.js express passport.js restify


    【解决方案1】:

    让我们看看,从哪里开始:

    • 是的,该请求是一个 ReadStream,如您所说,它将发出 data 事件。
    • 流中的第一个数据块存储在内存中,没有临时文件。

    您遇到的一般问题是您需要捕获从req 发出的数据,并在身份验证完成后重新发出它。 Connect 为您提供帮助。看起来passport-http目前不使用它们。

    如果您安装 pause 模块,它可以为您处理。

    试试这样的:

    var pause = require('pause');
    
    // Create our own middleware constructor.
    var bufferedAuthenticate = function(){
        // Set up standard authenticate handler passing arguments through.
        var authMiddleware = passport.authenticate.apply(passport, arguments);
    
        // Pass our own middleware instead that wraps passport-http.
        return function(req, res, next){
            // Pause the request before authenticating.
            var obj = pause(req);
            authMiddleware(req, res, function(err){
              next(err);
    
              // Emit any cached data events that fired while authenticating.
              obj.resume();
            });
        };
    };
    
    app.post('/upload',
        bufferedAuthenticate('basic', { session: false }),
        function(req, res, next) {
            var dataLength = 0;
    
            req.on('data', function(chunk) {
                console.log('loading');
                dataLength += chunk.length;
    
            }).on('end', function() {
                console.log('load end');
                console.log('contentLength: %s', req.headers['content-length']);
                console.log('dataLength:  : %s', dataLength);
                res.send(200);
            }); 
        }
    );
    

    【讨论】:

      猜你喜欢
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      • 2021-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多