AngularJS:在$http前调用的选项。post请求

时间:2022-08-22 19:38:58

I'm using AngularJS v1.2.4.

我用AngularJS v1.2.4。

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

我有一个问题,角发送一个预飞选项调用(Chrome显示了选项叫“取消”)并解决它:

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

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

这对我所有的资源调用都管用,一切都很好。

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.

现在,我正在尝试实现身份验证,以及使用用户凭证向服务器发送POST请求的登录页面。我看到了我以前面临的问题,但是$resource调用仍然可以正常工作。

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.

真正令人沮丧的是,问题是间歇性发生的;我将修改一些围绕头部的选项,然后它会工作一点,并且在没有任何代码更改的情况下停止工作。

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

我的服务器配置为CORS,并适用于curl和其他REST客户端。这里有一个例子:

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

Here's the $http.post call:

这是http。post调用:

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

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

当我的应用程序的调用工作时,这是选项请求的样子:

AngularJS:在$http前调用的选项。post请求

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

当它不起作用时,这是选项请求:

AngularJS:在$http前调用的选项。post请求

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

它看起来像一大堆的头属性不见了。有没有人遇到过类似的问题?

Edit:

编辑:

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

只是澄清一下,当它不起作用时,请求永远不会到达服务器——它会立即在浏览器中中止。

AngularJS:在$http前调用的选项。post请求

In Firebug, the request headers are:

在Firebug中,请求头是:

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

AngularJS:在$http前调用的选项。post请求

Update:

更新:

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.

我认为,通过将主机更改为一个不存在的服务器,我已经消除了服务器可能存在的问题。仍然看到同样的行为。

Here's some code:

这里有一些代码:

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;
        }
    };
});

and HTTP Config:

和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;
            }
        };
    });
}]);

3 个解决方案

#1


13  

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.

这种感觉可能与您在本地主机上命中一个https端点有关。这意味着您可能使用了某种自签名SSL证书,这可能意味着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.

我首先尝试直接访问/验证端点,看看Chrome是否会给您一个关于不受信任证书的警告。看看是否接受这个警告。

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

否则,当您在本地测试时,您可能只命中一个http端点,看看它是否解决了问题?

#2


9  

A huge thank you to Michael Cox for pointing me in the right direction. I accept his answer since it led me to the solution, but here are more details:

非常感谢迈克尔·考克斯给我指明了正确的方向。我接受他的回答,因为这让我找到了解决方案,但这里有更多的细节:

Looking into the https issue, I found:

在查看https问题时,我发现:

My problem was slightly different though. It still wasn't working after I followed the instructions in the links above. I read the chrome "untrusted" message carefully and it was something like "you're trying to access mylocalhost.com but the server is representing itself as ".

但我的问题略有不同。在我按照上面的链接操作之后,它仍然没有工作。我仔细阅读了chrome“不受信任”的消息,它类似于“你正在尝试访问mylocalhost.com,但服务器代表它自己”。

It turns out that my hastily created self signed certificate was "server.crt" when it should be "mylocalhost.crt"

事实证明,我匆忙创建的自签名证书就是“服务器”。crt"应该是"mylocalhost.crt"

#3


7  

You can not have allow-credentials together with Access-Control-Allow-Origin: *.

您不能与访问控制允许的来源一起使用许可证书:*。

Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding.

重要提示:当响应一个受信任的请求时,服务器必须指定一个域,不能使用野性的梳理。

Regarding GET requests, they do not need preflight etc if they don't have special headers.

对于GET请求,如果没有特殊的头信息,它们就不需要提前飞行。

Source: Mozilla Developer Network. (Best CORS link on the web!)

来源:Mozilla开发人员网络。(网上最好的CORS链接!)

#1


13  

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.

这种感觉可能与您在本地主机上命中一个https端点有关。这意味着您可能使用了某种自签名SSL证书,这可能意味着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.

我首先尝试直接访问/验证端点,看看Chrome是否会给您一个关于不受信任证书的警告。看看是否接受这个警告。

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

否则,当您在本地测试时,您可能只命中一个http端点,看看它是否解决了问题?

#2


9  

A huge thank you to Michael Cox for pointing me in the right direction. I accept his answer since it led me to the solution, but here are more details:

非常感谢迈克尔·考克斯给我指明了正确的方向。我接受他的回答,因为这让我找到了解决方案,但这里有更多的细节:

Looking into the https issue, I found:

在查看https问题时,我发现:

My problem was slightly different though. It still wasn't working after I followed the instructions in the links above. I read the chrome "untrusted" message carefully and it was something like "you're trying to access mylocalhost.com but the server is representing itself as ".

但我的问题略有不同。在我按照上面的链接操作之后,它仍然没有工作。我仔细阅读了chrome“不受信任”的消息,它类似于“你正在尝试访问mylocalhost.com,但服务器代表它自己”。

It turns out that my hastily created self signed certificate was "server.crt" when it should be "mylocalhost.crt"

事实证明,我匆忙创建的自签名证书就是“服务器”。crt"应该是"mylocalhost.crt"

#3


7  

You can not have allow-credentials together with Access-Control-Allow-Origin: *.

您不能与访问控制允许的来源一起使用许可证书:*。

Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding.

重要提示:当响应一个受信任的请求时,服务器必须指定一个域,不能使用野性的梳理。

Regarding GET requests, they do not need preflight etc if they don't have special headers.

对于GET请求,如果没有特殊的头信息,它们就不需要提前飞行。

Source: Mozilla Developer Network. (Best CORS link on the web!)

来源:Mozilla开发人员网络。(网上最好的CORS链接!)