How to avoid data loss of request flow after performing some authentication on node.js?

How do request streams work with node.js (express or restore)?

When a client is trying to upload audio, mpeg, or another binary to the server, the request must be a readable stream on the server. so that we could connect to another stream using request.pipe() , for example, to get the file from the request, and then upload the file to amazon s3 using knox.

When I use the asynchronous authentication method, part of the streaming data is lost and the length no longer matches the transmitted content-length header. Is there any way to avoid this behavior? Are the request stream data stored only in memory or is node.js storing data in some local temp folder?

 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'); }); 
+4
source share
1 answer

Let's see where to start:

  • Yes, the request is a ReadStream that will generate data events, as you said.
  • The first piece of data in the stream is stored in memory, there are no temporary files.

The common problem that you are facing is that you need to capture the data emitted from req and re-release it after authentication is complete. Connect provides assistants to do this for you. Pass-http doesn't seem to be using them at the moment.

If you install the pause module, it can handle this for you.

Try something like this:

 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); }); } ); 
+4
source

Source: https://habr.com/ru/post/1446390/


All Articles