【问题标题】:Modify Request body and then proxying in Node.js修改请求正文,然后在 Node.js 中代理
【发布时间】:2016-10-04 08:01:29
【问题描述】:

我是 Node.js 的相对新手。这两天我试图在 Node.js 中修改请求的正文,然后转发它。对于代理,我使用http-proxy 模块。

我要做的是在 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});
});

服务器(由 Spring MVC 制作的 REST)给了我异常 Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: null

【问题讨论】:

    标签: javascript node.js spring-mvc express proxy


    【解决方案1】:

    真正的问题是模块body-parserhttp-proxy 之间存在集成问题,如this 线程中所述。

    一种解决方案是在http-proxy 之后配置body-parser。如果您无法更改中间件的顺序(如我的情况),您可以在代理请求之前重新传输已解析的正文。

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

    【讨论】:

    • 这给了我错误Can't set headers after they are sent.。参照。 github.com/nodejitsu/node-http-proxy/issues/1168github.com/nodejitsu/node-http-proxy/issues/908.
    • 以防万一它对其他人有帮助:对我来说,我正在向有效负载添加更多信息,因此更新内容长度非常重要。我还必须在proxyReq.write() 之后包含proxyReq.end(),否则请求似乎在没有任何说明的情况下关闭。
    • 小心if (req.body),因为{} 是“真实的”。最好检查 body 对象中的道具:if (!!req.body && Object.keys(req.body).length > 0)
    【解决方案2】:

    为什么不为此使用快速链接? 在您的第一个函数中,只需执行以下操作:

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

    【讨论】:

    • 我必须先链接 body-parser 吗?因为我注意到它消耗了请求。
    • 您必须在 express 配置中使用 body-parser,例如:app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json());
    • 而且它不消费请求?下一个中间件可以使用它吗?
    • 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!!");
    });
    

    【讨论】:

    • 在调用 apiProxy 之前尝试记录你的 req.body,并给我们这个日志。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    相关资源
    最近更新 更多