web-dev-qa-db-ja.com

AngularJS:$ http.postリクエストに先行するOPTIONSプリフライトコール

私はAngularJS v1.2.4を使用しています。

AngularプリフライトOPTIONS呼び出しの送信(ChromeはOPTIONS呼び出しを「キャンセル」として表示していました))で問題が発生しました。

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

それはすべての$ resource呼び出しで機能し、すべてが良好でした。

今、私は認証を実装しようとしています、そしてユーザーの資格情報でPOSTリクエストをサーバーに送信します。前に直面していた問題を見ていますが、$ resourceが呼び出しますまだ正常に動作しています。

本当にイライラするのは、問題が断続的に発生することです。ヘッダーを取り巻くいくつかのオプションを変更すると、少し動作し、コードを変更せずに再び動作を停止します。

私のサーバーは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

$ http.post呼び出しは次のとおりです。

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

アプリからの呼び出しが機能する場合、OPTIONSリクエストは次のようになります。

enter image description here

動作しない場合、これはOPTIONSリクエストです:

enter image description here

たくさんのヘッダー属性が欠落しているようです。誰かが同様の問題に遭遇しましたか?

編集:

明確にするために、機能しない場合、リクエストはサーバーに到達することはありません。ブラウザで即座に中止されます。

enter image description here

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

enter image description here

更新:

ホストを存在しないサーバーに変更することで、サーバーの問題の可能性を排除しました。まだ同じ動作を見ています。

コードは次のとおりです。

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 Config:

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

これは、ローカルホスト上のhttpsエンドポイントにアクセスしているという事実に関連しているように思えます。つまり、おそらく何らかの自己署名SSL証明書を使用しているということです。つまり、Chromeは信頼できないと見なします。

最初に/ authenticateエンドポイントに直接アクセスして、Chromeが信頼できない証明書に関する警告を表示するかどうかを確認します。その警告を受け入れるかどうかを確認します。

それ以外の場合、おそらくローカルでテストしているときに、httpエンドポイントにヒットして、それが問題を解決するかどうかを確認できますか?

13
Michael Cox

マイケル・コックスに心から感謝します 私を正しい方向に向けてくれました 。私が解決策に導いたので、私は彼の答えを受け入れますが、詳細は次のとおりです。

Https問題を調べて、私は見つけました:

私の問題は少し異なりました。上記のリンクの指示に従った後、まだ機能していませんでした。 chrome "untrusted"メッセージを注意深く読みました。 "mylocalhost.comにアクセスしようとしていますが、サーバーは自分自身を表しています"のようなものでした。

急いで作成した自己署名証明書は、「mylocalhost.crt」であるはずの「server.crt」であったことが判明しました

9
shaunlim

allow-credentials 一緒に Access-Control-Allow-Origin: *

重要な注意:認証されたリクエストに応答するとき、サーバーはドメインを指定する必要があり、ワイルドカードを使用できません。

GETリクエストに関しては、特別なヘッダーがない場合、プリフライトなどは必要ありません。

ソース: Mozilla Developer Network 。 (ウェブ上の最高のCORSリンク!)

7
Zut