2016-11-16 3 views
2

Я написал промежуточное программное обеспечение Express для извлечения необработанного тела из запроса, и я установил его перед промежуточным программным обеспечением body-parser.Написание экспресс-промежуточного программного обеспечения для получения необработанного тела запроса перед телом-парсером

Моего заказ промежуточный слой звонит req.setEncoding('utf8'), но это вызывает следующую ошибку тела парсера:

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) 

Вот мой код:

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

Есть ли способ снят с, кодирующим ? Есть ли другой способ отсрочить сырое тело, но по-прежнему использовать тело-парсер после него?

+1

Используйте промежуточное программное обеспечение после bodyParser? – nicovank

+0

У вас есть опечатка в 'res.sendStatu (200);' также. – doublesharp

+0

Вы уверены, что вам нужно установить кодировку? – doublesharp

ответ

2

Вы вызываете next() внутри «done», что означает, что поток уже был использован. Вместо этого настройте обработчик для «данных», затем передайте запрос, используя next(). Событие «done», скорее всего, обрабатывается внутри bodyParser, поэтому после его выполнения у вас есть доступ к req.rawBody. Если бы это было не так, вы бы добавили другое промежуточное программное обеспечение, которое вызывает next() внутри req.on('done'), чтобы отложить остальное от обработки до тех пор, пока у вас не будет всех данных.

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

Если вам необходимо получить доступ к необработанному телу, вы также можете посмотреть в bodyParser.raw(). Это поместит необработанное тело в req.body, то же, что и bodyParse.json(), но может быть выполнено для условного запуска на основе типа контента - проверьте options.type.

+1

'в вашем примере внутренняя функция никогда не называется' да, это ... функция 'myMiddleware' возвращает функцию, и он называет ее позже' app.use (myMiddleware()) ' – nicovank

+0

Вы правы, но он не переходит в 'req, res, next', поэтому они не выполняются в правильном контексте. – doublesharp

+0

Да, они ... Вот скрипка: https://jsfiddle.net/8zn44d0c/ – nicovank

0

Я рекомендую другой подход, так как ваш текущий подход на самом деле потребляет сообщение и делает его невозможным для тела парсер, чтобы прочитать его (и есть куча примеров ошибок краевых, которые возникают по телефону next синхронно):

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

Это будет читать любые application/json запрос как JSON, а все остальное как текст.

Если вы должны иметь объект JSON в дополнение к тексту, я рекомендую разборе его самостоятельно:

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

Я думаю, что синтаксический анализ сам по себе станет для вас способом. – kiewic

1

Оказывается, что body-parser имеет проверить возможность вызвать функцию, когда тело запроса имеет был прочитан. Функция получает тело в качестве буфера.

Вот пример:

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

 Смежные вопросы

  • Нет связанных вопросов^_^