尝试从 api 获取令牌时节点获取的错误行为

Posted

技术标签:

【中文标题】尝试从 api 获取令牌时节点获取的错误行为【英文标题】:incorrect behaviour of node-fetch while trying to get token from an api 【发布时间】:2018-01-13 09:16:27 【问题描述】:

我想使用一些节点获取代码连接到外部 api。我的代码首先发送登录详细信息,并且应该从 api 接收令牌。然后这个令牌用于以后的所有通信。

代码如下:

import fetch from 'node-fetch';
function getTokenForAuth(info) 
    try 
        var auth_token = '';
        fetch(api_url + '/api/api-token/', 
            method: 'POST',
            body: JSON.stringify(info),

            headers: 
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            
        )
        .then(function(res) 
            return res.json();
        )
        .then(function(json) 
            auth_token = json;
        )
        return auth_token.token;
    

    catch (e) 
        console.log('[-] Error: Token Not Received');
        console.log('[!] Exception: ' + e);
    


function getJSONFromRelativeURL(relativeURL, info) 
    return fetch(`$api_url$relativeURL`, 
        method: 'GET',
        headers: 
            'Content-Type': 'application/json',
            'Authorization': 'Token ' + getTokenForAuth(info)
        
    )
    .then(function(res) 
        console.log(res);
        return res.json();
    )
    .then(function(json) 
        console.log(json);
    )

getJSONFromRelativeURL() 函数的请求标头中,如果我对令牌进行硬编码,我会得到正确的结果。但是如果我现在运行代码,我会收到一条错误消息: detail: 'Invalid token.'

我认为这是因为 fetch 函数中 promise 的异步性质,因此它有时无法在 getJSONFromRelativeURL() 被调用之前及时发送令牌。我不确定这个假设,也不知道如何纠正。

【问题讨论】:

getTokenForAuth 返回一个承诺对象。所以你没有设置授权头。尝试控制它,您将看到一个对象而不是令牌。必须调用getTokenForAuth 并在其中.then() 调用getJSONFromRelativeURL 函数。这样您就可以将令牌作为字符串。还必须从 then 内部而不是外部返回令牌。 反正我是第一个回答的。是什么让您不理解我的回答,以便我改进? 我刚刚选择了另一个答案,因为它的代码更好地放在一起,他还回答了我的假设(我不确定)。我认为,回首往事,他的答案也以更好的方式与逻辑流程组合在一起(向我展示我做错了什么,然后逐步回答)。 【参考方案1】:

你的问题在这里:

.then(function(json) 
    auth_token = json;
)
return auth_token.token;

您的 return 语句位于 Promise 链之外。这意味着,在您点击return 时,fetch 请求甚至还没有机会运行。你基本上只是告诉fetch Promise 链做什么当它确实返回时要做什么。

本质上

我认为这是因为 fetch 函数中 promise 的异步性质,因此它有时无法在调用 getJSONFromRelativeURL() 之前及时发送令牌。

100% 正确。

你需要做的是稍微重组一下:

function getTokenForAuth(info) 
  return fetch(api_url + "/api/api-token/", 
    method: "POST",
    body: JSON.stringify(info),

    headers: 
      "Content-Type": "application/json",
      Accept: "application/json"
    
  ).then(function(res) 
    return res.json();
  );


function getJSONFromRelativeURL(relativeURL, info) 
  return getTokenForAuth(info)
    .then(function(token) 
      return fetch(`$api_url$relativeURL`, 
        method: "GET",
        headers: 
          "Content-Type": "application/json",
          Authorization: `Token $token`
        
      );
    )
    .then(function(res) 
      console.log(res);
      return res.json();
    )
    .then(function(json) 
      console.log(json);
    );

【讨论】:

【参考方案2】:

尚未对其进行测试,但它看起来类似于以下内容。对于错误处理,在每个链的末尾使用 .catch(()=>) 。

   function getTokenForAuth(info) 

            var auth_token = '';
            return fetch(api_url + '/api/api-token/', 
                method: 'POST',
                body: JSON.stringify(info),

                headers: 
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                
            )
            .then(function(res) 
                return res.json();
            )
           


    function getJSONFromRelativeURL(relativeURL, info, token) 
        return fetch(`$api_url$relativeURL`, 
            method: 'GET',
            headers: 
                'Content-Type': 'application/json',
                'Authorization': 'Token ' + token
            
        )
        .then(function(res) 
            console.log(res);
            return res.json();
        )
        .then(function(json) 
            console.log(json);
        )
    


    getTokenForAuth(info)
    .then((token)=>
      return getJSONFromRelativeURL(relativeURL, info, token)
    )

【讨论】:

以上是关于尝试从 api 获取令牌时节点获取的错误行为的主要内容,如果未能解决你的问题,请参考以下文章

从 reddit api 获取 api oauth 访问令牌

无法获取 lyft api 的访问令牌

尝试请求令牌时出现 Twitter API 错误

当我尝试验证测试购买产品时 - 出现错误 410?购买.产品获取

使用 Angular 和 JWT 令牌持续登录

获取访问令牌时服务帐户 API 错误