2016-11-16 1 views
2

J'ai écrit un middleware Express pour récupérer le corps brut de la demande, et je l'ai mis avant le middleware body-parser.Écriture middleware express pour obtenir le corps de la requête brute avant body-parser

Mon middleware personnalisé appelle req.setEncoding('utf8'), mais cela provoque l'erreur corps analyseur suivant:

Error: stream encoding should not be set

at readStream (/node_modules/body-parser/node_modules/raw-body/index.js:211:17) 
at getRawBody (/node_modules/body-parser/node_modules/raw-body/index.js:106:12) 
at read (/node_modules/body-parser/lib/read.js:76:3) 
at jsonParser (/node_modules/body-parser/lib/types/json.js:127:5) 

Voici mon code:

var express = require('express'); 
var bodyParser = require('body-parser') 

function myMiddleware() { 
    return function(req, res, next) { 
    req.rawBody = ''; 
    req.setEncoding('utf8'); 

    req.on('data', function(chunk) { 
     req.rawBody += chunk; 
    }); 

    req.on('end', function() { 
     next(); 
    }); 
    } 
} 

var app = express(); 
app.use(myMiddleware()); 
app.use(bodyParser.json()); 

var listener = app.listen(3000, function() { 
}); 

app.get('/webhook/', function (req, res) { 
    res.sendStatus(200); 
}); 

est-il un moyen de unset l'encodage ? Y a-t-il une autre façon de retirer le corps brut, mais encore utiliser body-parser après?

+1

Utilisez votre middleware après bodyParser? – nicovank

+0

Vous avez également une faute de frappe dans 'res.sendStatu (200); – doublesharp

+0

Etes-vous sûr de vouloir définir l'encodage? – doublesharp

Répondre

2

Vous appelez next() dans "done", ce qui signifie que le flux a déjà été consommé. Au lieu de cela, configurez le gestionnaire pour "données" puis transmettez la demande en utilisant next(). L'événement "done" est probablement géré à l'intérieur de bodyParser donc après son exécution, vous avez accès à req.rawBody. Si ce n'était pas le cas, vous ajouteriez un autre logiciel intermédiaire qui appelle next() à l'intérieur d'un req.on('done') pour que le reste du traitement ne soit pas traité tant que vous n'avez pas toutes les données.

// custom middleware - req, res, next must be arguments on the top level function 
function myMiddleware(req, res, next) { 
    req.rawBody = ''; 

    req.on('data', function(chunk) { 
    req.rawBody += chunk; 
    }); 

    // call next() outside of 'end' after setting 'data' handler 
    next(); 
} 

// your middleware 
app.use(myMiddleware); 

// bodyparser 
app.use(bodyParser.json()) 

// test that it worked 
function afterMiddleware(req, res, next) { 
    console.log(req.rawBody); 
    next(); 
} 

app.use(afterMiddleware); 

Si vous avez besoin d'accéder au corps cru que vous pourriez également regarder dans bodyParser.raw(). Cela va mettre le corps brut dans req.body, même que bodyParse.json(), mais peut être fait pour fonctionner conditionnellement basé sur le type de contenu - consultez options.type.

+1

'dans votre exemple la fonction interne n'est jamais appelée' oui c'est .... la fonction' myMiddleware' renvoie la fonction et il l'appelle plus tard 'app.use (myMiddleware())' – nicovank

+0

Vous avez raison, mais il ne passe pas dans 'req, res, next' donc ils ne sont pas exécutés dans le bon contexte – doublesharp

+0

Oui ils sont .... Voici un violon: https://jsfiddle.net/8zn44d0c/ – nicovank

0

Je recommande une approche différente, puisque votre approche actuelle consomme en fait le message et rend impossible pour le corps-analyseur pour le lire (et il y a un tas de bugs de cas de pointe qui naissent en appelant next synchrone):

app.use(bodyParser.json()); 
app.use(bodyParser.text({type: '*/*'})); 

Ceci va lire n'importe quelle demande application/json en tant que JSON, et tout le reste en tant que texte.

Si vous devez avoir l'objet JSON en plus du texte, je vous recommande l'analyse syntaxique vous-même:

app.use(bodyParser.text({type: '*/*'})); 
app.use(myMiddleware); 

function myMiddleware(req, res, next) { 
    req.rawBody = req.body; 
    if(req.headers['content-type'] === 'application/json') { 
     req.body = JSON.parse(req.body); 
    } 
    next(); 
} 
+0

Je pense que l'analyser moi-même sera la voie à suivre. – kiewic

1

Il se avère que body-parser a une option verify d'appeler une fonction lorsque le corps de la demande a été lu. La fonction reçoit le corps en tant que tampon.

est un exemple:

var express = require('express'); 
var bodyParser = require('body-parser') 

function verifyRequest() { 
    return function(req, res, buf, encoding) { 
    // The raw body is contained in 'buf' 
    console.log(buf.toString('utf8')); 
    }; 
} 

var app = express(); 
var listener = app.listen(3000); 

// Hook 'verifyRequest' with body-parser here. 
app.use(bodyParser.json({ verify: verifyRequest })) 

app.post('/webhook/', function (req, res) { 
    res.status(200).send("done!"); 
});