AngularJS:在$ http.post请求之前的OPTIONS preflight调用 [英] AngularJS: OPTIONS preflight call preceding a $http.post request

查看:1300
本文介绍了AngularJS:在$ http.post请求之前的OPTIONS preflight调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用AngularJS v1.2.4。

I'm using AngularJS v1.2.4.

我有一个问题Angular发送预检OPTIONS调用(Chrome显示OPTIONS调用为已取消)并解析为:

I had an issue with Angular sending a preflight OPTIONS call (Chrome was showing the OPTIONS call as 'canceled') and resolved it with:

$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

这适用于我所有的$ resource调用,一切都很好。

That worked for all my $resource calls, and everything was good.

现在我试图实现身份验证,登录页面使用用户的凭据向我的服务器发送一个POST请求。我看到了我面对的问题,但$资源调用仍然工作正常。

Now I'm trying to implementation authentication, and a login page that sends a POST request to my server with the user's credentials. I'm seeing the problem I was facing before, but $resource calls are still working fine.

真正令人沮丧的是,问题是间歇性发生;我将更改标头周围的几个选项,然后它会工作一会儿,并停止工作,没有任何代码更改。

What's really frustrating is that the problem happens intermittently; I'll change a few options surrounding the headers, then it'll work for a bit, and stop working again without any code change.

我的服务器配置为CORS并与curl和其他REST客户端一样正常工作。例如:

My server is configured for CORS and works fine with curl, and other REST clients. Here's an example:

curl -X OPTIONS -ik 'https://localhost:3001/authenticate' -H "Origin: https://localhost:8001"
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
content-length: 2
cache-control: no-cache
access-control-allow-origin: *
access-control-max-age: 86400
access-control-allow-methods: GET, HEAD, POST, PUT, DELETE, OPTIONS
access-control-allow-headers: Authorization, Content-Type, If-None-Match, Access-Control-Allow-Headers, Content-Type
access-control-expose-headers: WWW-Authenticate, Server-Authorization
set-cookie: session=Fe26.2**94705d49717d1273197ae86ce6661775627d7c6066547b757118c90c056e393b*2KYqhATojPoQhpB2OwhDwg*W9GsJjK-F-UPqIIHTBHHZx1RXipo0zvr97_LtTLMscRkKqLqr8H6WiGd2kczVwL5M25FBlB1su0JZllq2QB-9w**5510263d744a9d5dc879a89b314f6379d17a39610d70017d60acef01fa63ec10*pkC9zEOJTY_skGhb4corYRGkUNGJUr8m5O1US2YhaRE; Secure; Path=/
Date: Wed, 18 Dec 2013 23:35:56 GMT
Connection: keep-alive

这里是$ http.post调用:

Here's the $http.post call:

var authRequest = $http.post('https://' + $location.host() + ':3001/authenticate', {email: email, password: password});

当我的应用程式呼叫工作时,这是OPTIONS请求的样子:

When the call from my app works, this is how the OPTIONS request looks like:

>

当它不工作时,这是OPTIONS请求:

When it doesn't work, this is the OPTIONS request:

看起来整个标题属性都丢失了。有没有人遇到过类似的问题?

It looks like a whole bunch of header attributes are missing. Has anyone encountered a similar issue?

编辑:

该请求从不会发送到服务器 - 它会在浏览器中立即中止。

Just to clarify, when it doesn't work, the request never makes it to the server - it's instantly aborted in the browser.

在Firebug中,请求标头是:

In Firebug, the request headers are:

OPTIONS /authenticate HTTP/1.1
Host: localhost:3001
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:25.0) Gecko/20100101 Firefox/25.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.91,en-GB;q=0.82,fr-FR;q=0.73,fr;q=0.64,utf-8;q=0.55,utf;q=0.45,de-DE;q=0.36,de;q=0.27,en-sg;q=0.18,en-ca;q=0.09
Accept-Encoding: gzip, deflate
Origin: https://localhost:8001
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Proxy-Authorization: Basic cGF0cmljZUB6b25nLmNvbTpjaGFuZ2VtZQ==
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

更新:

我已经消除了服务器可能出现的问题,我认为,通过将主机更改为不存在的服务器。仍然显示相同的行为。

I've eliminated the possibly of a problem with the server, I think, by changing the host to a non-existent server. Still seeing the same behavior.

以下是一些代码:

App.services.factory('AuthService', function ($http, $location, $q) {

    var currentUser;

    return {
        authenticate: function (email, password) {

            //promise to return
            var deferred = $q.defer();

            var authRequest = $http.post('https://this.does.not.exist.com:3001/authenticate', {email: email, password: password});

            authRequest.success(function (data, status, header, config) {
                currentUser = data;
                console.log('currentUser in service set to:');
                console.log(currentUser);
                //resolve promise
                deferred.resolve();
            });

            authRequest.error(function (data, status, header, config) {
                console.log('authentication error');
                console.log(status);
                console.log(data);
                console.log(header);
                console.log(config);

                //reject promise
                deferred.reject('authentication failed..');
            });

            return deferred.promise;
        },
        isAuthenticated: function () {
            return currentUser !== undefined;
        }
    };
});

和HTTP配置:

App.config(['$httpProvider', function ($httpProvider) {

    $httpProvider.defaults.useXDomain = true;
    //$httpProvider.defaults.headers.common = {};

    console.log('logging out headers');
    console.log($httpProvider.defaults);
    console.log($httpProvider.defaults.headers.common);
    console.log($httpProvider.defaults.headers.post);
    console.log($httpProvider.defaults.headers.put);
    console.log($httpProvider.defaults.headers.patch);
    console.log('end logging out headers');

    $httpProvider.defaults.headers.common = {Accept: "application/json, text/plain, */*"};
    $httpProvider.defaults.headers.post = {"Content-Type": "application/json;charset=utf-8"};

    console.log('after: logging out headers');
    console.log($httpProvider.defaults.headers.common);
    console.log($httpProvider.defaults.headers.post);
    console.log($httpProvider.defaults.headers.put);
    console.log($httpProvider.defaults.headers.patch);
    console.log('after: end logging out headers');

    $httpProvider.interceptors.push(function ($location, $injector) {
        return {
            'request': function (config) {

                console.log('in request interceptor!');

                var path = $location.path();
                console.log('request: ' + path);

                //injected manually to get around circular dependency problem.
                var AuthService = $injector.get('AuthService');
                console.log(AuthService);
                console.log(config);

                if (!AuthService.isAuthenticated() && $location.path() != '/login') {
                    console.log('user is not logged in.');
                    $location.path('/login');
                }

                //add headers
                console.log(config.headers);
                return config;
            }
        };
    });
}]);


推荐答案

这感觉像是可能与您在本地主机上访问 https 端点。这意味着您可能使用某种自签名的SSL证书,这可能意味着Chrome认为它不受信任。

This feels like it might be related to the fact that you're hitting an https endpoint on your localhost. That means you're probably using some sort of self-signed SSL certificate, which may mean Chrome considers it untrusted.

我会先尝试直接进入/ authenticate端点并查看Chrome是否为您提供有关不受信任的证书的警告。

I'd first try going directly to the /authenticate endpoint and see if Chrome gives you a warning about an untrusted certificate. See if accepting that warning works.

否则,当您在本地测试时,您只需点击 http 端点,看看是否能解决问题?

Otherwise, possibly while you're testing locally you can hit just an http endpoint and see if that solves things?

这篇关于AngularJS:在$ http.post请求之前的OPTIONS preflight调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆