AngularJS - HTTP 请求在控制器中发出预检请求,但不在 app.js 中

Posted

技术标签:

【中文标题】AngularJS - HTTP 请求在控制器中发出预检请求,但不在 app.js 中【英文标题】:AngularJS - HTTP request makes preflight request in controllers but not in app.js 【发布时间】:2016-01-17 18:42:04 【问题描述】:

我有一个与外部 API 通信的应用。我的应用程序的每个页面都有一个控制器。如果我在我的一个控制器中发出 HTTP GET 请求,它会发送一个 OPTIONS 预检请求,我会收到一个错误:

XMLHttpRequest 无法加载 http://dev/api/?email_address=email@email.com&password=111111。预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权。

但是,如果我复制粘贴相同的代码并将其粘贴到我的 app.js 文件中,它会完美运行并返回数据。我发现这样它也只发送 GET 请求,而不是 OPTIONS 请求。

我尝试将标题内容类型添加为“文本/纯文本”到我的请求中,但这并没有改变。如果我尝试使用 jQuery 发出请求,它工作得很好,只发送 GET 请求,不管代码是在控制器中还是在 app.js 文件中。这是完整的控制器代码(Angular 形式):

angular.module('website.homepage', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) 
    $routeProvider.when('/', 
        templateUrl: 'homepage/view.html',
        controller: 'HomepageCtrl',
        resolve: 
            data: function($q, $http, $route, $rootScope) 
                var deferred = $q.defer();
                $http(method: 'GET', url: $rootScope.apiURL + 'home')
                    .then(function(data) 
                        deferred.resolve(data);
                    );
                return deferred.promise;
            
        
    )
])
.controller('HomepageCtrl', function ($scope, $http, data) 

        var url = "http://dev.api";

        $http(
            url: url,
            dataType: 'json',
            method: "GET",
            data: '',
            params: 
                email_address: 'email@email.com',
                password: '111111'
            ,
            headers: 
                'Content-Type': 'text/plain'
            
        )
        .success(function(response) 
            console.log(response);

        )
       .error(function(response) 
            console.log(response);
       );


 )
 .config(function ( $httpProvider) 
     delete $httpProvider.defaults.headers.common['X-Requested-With'];
 )

【问题讨论】:

【参考方案1】:

对代表跨域资源共享的概念CORS 进行研究。 CORS 是一种允许从其他域请求 Internet 上一个位置上的资源的技术。 作为一项安全功能,由于same origin policy 的概念,默认情况下禁止跨域请求。

您收到错误是因为您尝试发出 cross-origin 请求,而事实上,这是不允许的。

尝试删除Angular默认发送的标头以防止此类请求:

angular.module('someModule') 
.config(function ( $httpProvider)         
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
)...

更新

我认为,一个模块中只能有 一个 配置块。因此,您需要将两种配置合并为一个:

angular.module('website.homepage', ['ngRoute'])
.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider)  // inject the other provider here
$routeProvider.when('/', 
    templateUrl: 'homepage/view.html',
    controller: 'HomepageCtrl',
    resolve: 
        data: function($q, $http, $route, $rootScope) 
            var deferred = $q.defer();
            $http(method: 'GET', url: $rootScope.apiURL + 'home')
                .then(function(data) 
                    deferred.resolve(data);
                );
            return deferred.promise;
        
      
    );

    delete $httpProvider.defaults.headers.common['X-Requested-With'];
])...   // rest of your code (services, factories, whatever)

【讨论】:

感谢您的回答。不幸的是,这仍然不能解决问题。 您在控制台中得到了什么? 我遇到了和以前一样的问题。 XMLHttpRequest 无法加载 dev.api/?email_address=email@email.com&password=111111。预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段授权。 您是否删除了 Angular config 中指出的特定标头?还请分享您在控制台中收到的错误文本(最好使用带有 Angular 的 Chrome 进行调试)。 是的,我做到了。我编辑了我的问题以包含完整的控制器代码。错误消息也已更新,这就是我在控制台中得到的全部内容。谢谢。

以上是关于AngularJS - HTTP 请求在控制器中发出预检请求,但不在 app.js 中的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS $http 对 Web 服务的请求需要 CORS

TypeScript/angularJS HTTP GET 请求中的范围

AngularJS 工厂和控制器代码,不产生任何东西

访问控制允许来源 angularjs 到 php

angularjs学习笔记--$http数据渲染到表格路由依赖注入provider

如何在 AngularJS 中取消 $http 请求?