简体   繁体   English

更新nodejs http.request中的标头

[英]Update headers in a nodejs http.request

There is a way in nodejs to modify response headers when calling a second nested http.request that return some data from another server ? 当调用第二个嵌套的http.request从另一个服务器返回一些数据时,nodejs中有一种方法可以修改响应头。 I always get this error, from the below functions... 我总是从以下功能中收到此错误...

 catch error: Error: Can't set headers after they are sent.

Main function from where I call to check if the token is valid: req.on('end', function (){ 从中调用以检查令牌是否有效的主要函数:req.on('end',function(){
console.log('GET to /api, Do I have privileges with %s?', access_token); console.log('获取/ api,我对%s有特权吗?',access_token); validadToken(req, res, next); validadToken(req,res,next); }); });

This is the funciton to validate the token against the OAuth2 server, if the respond is 401, I tried to obtain an new refresh_token: 这是针对OAuth2服务器验证令牌的功能,如果响应为401,我尝试获取新的refresh_token:

    function validadToken (req, res, next ) {
        var options = { port: 8080, 
                        path: '/api', 
                        host: 'localhost', 
                        method: 'GET' , 
                        headers: {'Authorization': 'Bearer '+ access_token,
                              'Content-Type':'application/x-www-form-urlencoded'} };
        req2 = http.request(options, 
            function (response){
                response.setEncoding('utf8');
                response.on('data', function (chunk) {
                    console.log(".-response=> ", chunk);
                    console.log("statusCode: " + response.statusCode);

                    if(response.statusCode == 401){
                        console.log();
                        console.log("===>>>> call to renew / wait for me");
                        renewToken(response, res, next); 

                    }else if(response.statusCode === 200){
                        console.log("Valid Token... we keep it going!");
                    }
                    next();             
                });  
            });
        req2.write(formData);

        req2.end();         
}

From here I try to get the refresh token, but when I try to update the new value in the headers I get the above error. 从这里我尝试获取刷新令牌,但是当我尝试更新标头中的新值时,出现上述错误。 The value for refresh_token is recovery from a response from the previously function refresh_token的值是从先前功能的响应中恢复

    function renewToken (req, res){
    var userUrl = 'grant_type=refresh_token&refresh_token='+refresh_token+'&client_id=XXX&client_secret=XXX';
    var optRenew = {    port: 8080, 
                        path: '/token', 
                        host: 'localhost', 
                        method: 'POST' , 
                        headers: {'Content-Type':'application/x-www-form-urlencoded'} };

    renew = http.request(optRenew, 
            function (responseRenew){
              console.log("responseRenew");
              responseRenew.setEncoding('utf8');

              responseRenew.on('data', function (chunk){
                        console.log(".-responseRenew=> ", chunk);
                        console.log(".-responseRenew=> ", responseRenew.statusCode);
                        accessTokenValue = getToken("access_token", chunk, ',', ':', '"');
                        refreshTokenValue = getToken("refresh_token", chunk, ',', ':', '"'); 
                        console.log("Headers Sent (renew) ? "+ res.headersSent);
                        console.log("¡¡¡New values!!!\n" + accessTokenValue +' '+ refreshTokenValue);     

                        res.setHeader("Set-Cookie", ["ninja="+accessTokenValue, "samurai="+refreshTokenValue]);
                        console.log("envio ....");
                      })
            });
    renew.write(userUrl);
    renew.end();  
}

I think I found it 我想我找到了

if(response.statusCode == 401) {
  console.log();
  console.log("===>>>> call to renew / wait for me");
  renewToken(response, res, next); 

} else if(response.statusCode === 200) {
  console.log("Valid Token... we keep it going!");
}
next();

When the token doesn't need to be renewed you call next and all is ok, but when renewToken is called you have a problem: http.request is an asynchronous call, renewToken returns before the code that process the renew response is executed, so the call to next is done before the renewed token is known. 当不需要更新令牌时,您next调用,一切都OK,但是在renewToken时,您遇到了一个问题: http.request是异步调用,在执行处理renew响应的代码之前, renewToken返回。在知道更新的令牌之前完成对next的调用。 When you call next the next middleware is called, here probably the next middleware will send back the response before the renewed token will be available and this explains your error: after the next middleware completes the response you try to set one of the response headers 当您next调用next一个中间件时,此处可能是下一个中间件在更新的令牌可用之前发送回响应,这解释了您的错误:在下一个中间件完成响应后,您尝试设置响应头之一

The solution actually is really easy (I'll skip some code) 该解决方案实际上非常简单(我将跳过一些代码)

function validadToken(req, res, next) {
  ...
  req2 = http.request(options, function (response) {
    response.setEncoding('utf8');
    response.on('data', function(chunk) {
      ...
      if (response.statusCode == 401) {
        ...
        renewToken(req, res, next); 

      } else if (response.statusCode === 200) {
        console.log("Valid Token... we keep it going!");
        next();
      } else {
        // TODO: you should deal with the other cases
      }                
    });  
  });
  req2.write(formData);
  req2.end();         
}

function renewToken(req, res, next) {
  ...

  renew = http.request(optRenew, function (responseRenew){
     ...
     responseRenew.on('data', function(chunk){
       ...    
       res.setHeader("Set-Cookie", ["ninja="+accessTokenValue, "samurai="+refreshTokenValue]);
       console.log("envio ....");

       // NOW IT'S THE TIME TO CALL THE NEXT MIDDLEWARE
       next()
     })
   });
   renew.write(userUrl);
   renew.end();  
}

TL;DR; TL; DR; you should call next only after you got the token 你应该叫next你得到了令牌后,才

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM