Изменить тело запроса, а затем проксировать в Node.js

#javascript #node.js #spring-mvc #express #proxy

#javascript #node.js #spring-mvc #выразить #прокси

Вопрос:

Я относительный новичок в Node.js . Прошло два дня, когда я пытаюсь изменить тело запроса в Node.js а затем переадресовал его. Для проксирования я использую http-proxy module.

Что мне нужно сделать, так это перехватить пароль пользователя внутри объекта JSON, зашифровать его и установить новый зашифрованный пароль внутри тела запроса.

Проблема в том, что каждый раз, когда я пытаюсь собрать тело запроса, я его использую (т. Е. Использую body-parser ). Как я могу выполнить эту задачу? Я знаю, что запрос в узле рассматривается как поток.

Для полноты картины я использую express для цепочки несколько операций перед проксированием.

Редактировать

Тот факт, что я должен проксировать запрос, не бесполезен. Он следует коду, который я пытаюсь использовать.

 function encipher(req, res, next){
    var password = req.body.password;
    var encryptionData = Crypto().saltHashPassword(password);
    req.body.password = encryptionData.passwordHash;
    req.body['salt'] = encryptionData.salt;
    next();
}

server.post("/users", bodyParser.json(), encipher, function(req, res) {
    apiProxy.web(req, res, {target: apiUserForwardingUrl});
});
  

Сервер (REST, созданный Spring MVC) выдает мне исключение Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: null

Ответ №1:

Реальная проблема заключается в том, что существует проблема интеграции между модулями body-parser и http-proxy , как указано в этой теме .

Одним из решений является настройка body-parser after http-proxy . Если вы не можете изменить порядок промежуточного программного обеспечения (как в моем случае), вы можете повторно передать проанализированное тело перед проксированием запроса.

 // restream parsed body before proxying
proxy.on('proxyReq', function(proxyReq, req, res, options) {
    if (req.body) {
        let bodyData = JSON.stringify(req.body);
        // if content-type is application/x-www-form-urlencoded -> we need to change to application/json
        proxyReq.setHeader('Content-Type','application/json');
        proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
        // stream the content
        proxyReq.write(bodyData);
    }
}
  

Комментарии:

1. Это выдает ошибку Can't set headers after they are sent. . Cf. github.com/nodejitsu/node-http-proxy/issues/1168 и github.com/nodejitsu/node-http-proxy/issues/908 .

2. На всякий случай, если это полезно для других: для меня я добавлял больше информации в полезную нагрузку, поэтому обновление длины содержимого было очень важно. Мне также пришлось включить proxyReq.end() after proxyReq.write() или запрос, казалось, закрылся без каких-либо указаний на причину.

3. Будьте осторожны с if (req.body) , поскольку {} это «правдиво». Лучше проверять реквизиты в объекте body: if (!!req.body amp;amp; Object.keys(req.body).length > 0)

Ответ №2:

Почему бы не использовать для этого экспресс-цепочку? В вашей первой функции просто сделайте что-то вроде этого :

req.body.password = encrypt(req.body.password); next();

Комментарии:

1. Должен ли я сначала связать body-parser? Потому что я заметил, что он использует запрос.

2. Вы должны использовать body-parser в своей экспресс-конфигурации, например : app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json());

3. И он не использует запрос? Будет ли оно доступно для следующего промежуточного программного обеспечения?

4. bodyParser преобразует каждый запрос вашего сервера, затем в каждом промежуточном программном обеспечении вы сможете делать то, что хотите, с req.body

Ответ №3:

Вам просто нужно использовать промежуточное программное обеспечение.

body-parser это также просто промежуточное программное обеспечение, которое анализирует тела запросов и помещает его под req.body

Вы можете сделать что-то вроде этого:

 app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

function encryptPassword(req, res, next) {
    req.body.password = encrypt(req.body.password);
    // You can do anything really here and modify the req

    //call next after you are done to pass on to next function

    next();
}

app.use(encryptPassword);
  

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

Вы также можете использовать промежуточные программы в определенных маршрутах:

 app.post('/password', encryptPassword, function(req, res) {
     // Here the req.body.password is the encrypted password....

     // You can do other operations related to this endpoint, like store password in database

     return res.status(201).send("Password updated!!");
});
  

Комментарии:

1. Попробуйте зарегистрировать свой req.body перед вызовом apiProxy и предоставьте нам этот журнал.