角请求拦截器中的服务调用导致错误

时间:2016-01-21 15:31:26

标签: angularjs

我想在我的应用程序中使用请求拦截器将验证代码添加到请求中(用于CSRF保护)。我的代码现在看起来像这样:

      $httpProvider.interceptors.push(function($q, $injector, AppConst) {
      return {
          request: function(request) {
              var VerifyCodeService = $injector.get('VerifyCodeService');
              var verifyCodeUrl = AppConst.apiUrl + '/app/verifyCode'

              if(request.url!=verifyCodeUrl && request.data!=undefined){
                  VerifyCodeService.getCode()
                      .then(function(data) {
                          if (AppConst.serviceResponseOk==data.result) {
                              request.data.verifyCode = data.verifyCode;
                              return request;
                          } else {
                              console.log('error');
                              return request;
                          }
                      }, function(error) {
                          console.log('error:' + error);
                          return request;
                      });
              } else {
                  return request;
              }
          }
      };
  });

但由于某种原因,我不断收到此错误:

TypeError: Cannot read property 'headers' of undefined
at serverRequest (angular.js:10028)
at processQueue (angular.js:14567)
at angular.js:14583
at Scope.$eval (angular.js:15846)
at Scope.$digest (angular.js:15657)
at Scope.$apply (angular.js:15951)
at done (angular.js:10364)
at completeRequest (angular.js:10536)
at XMLHttpRequest.requestLoaded (angular.js:10477)

有谁知道发生了什么事?

1 个答案:

答案 0 :(得分:1)

如果我读得正确,你正在制作一个XHR,它会触发另一个XHR来获取CSRF令牌并将其添加到原始请求的数据对象中。我认为问题是第二个XHR。第二个请求就像第一个请求一样异步,所以你不能只从then方法返回。

尝试在if语句中返回第二个XHR生成的承诺(在then之后的第二个XHR之后在内部return request;调用中解析。

         if(request.url!=verifyCodeUrl && request.data!=undefined){
              var secondXhr = VerifyCodeService.getCode()
                  .then(function(data) {
                      if (AppConst.serviceResponseOk==data.result) {
                          request.data.verifyCode = data.verifyCode;
                          return request;
                      } else {
                          console.log('error');
                          return request;
                      }
                  }, function(error) {
                      console.log('error:' + error);
                      return request;
                  });
              return secondXhr; 
          } else {
              return request;
          }

来自Angular文档的Interceptors section(添加了粗体):

  

请求:使用http配置对象调用拦截器。该   函数可以自由修改配置对象或创建新对象。该   函数需要直接返回配置对象,或承诺   包含配置或新的配置对象

另一方面,看起来你在每个XHR中引入了一个重要的延迟,因为在返回令牌之前你基本上阻止了每个请求。

每个响应返回标头中下一个请求的新标记的不同实现可以工作(只要您没有并发请求(!)),或每页加载CSRF标记(如果您有完整页面)重新加载)可能是选项。如果您想进行更改,我确信互联网上有建议。