web-dev-qa-db-ja.com

OPTIONSプリフライトリクエストをスキップする方法

PhoneGapアプリを開発しましたが、現在はモバイルWebサイトに変換されています。 1つの小さな不具合以外はすべてスムーズに機能します。 POSTリクエストを介して特定のサードパーティAPIを使用します。これはアプリでは正常に機能しますが、モバイルWebサイトバージョンでは失敗します。

よく見てみると、AngularJS(実際にはブラウザだと思います)が最初にOPTIONSリクエストを送信しているようです。今日、CORSについて多くのことを学びましたが、CORSを完全に無効にする方法がわかりません。私はそのAPIにアクセスできません(したがって、その側での変更は不可能です)が、彼らは私が取り組んでいるドメインをAccess-Control-Allow-Originヘッダーに追加しました。

これは私が話しているコードです:

        var request = {
                language: 'fr',
                barcodes: [
                    {
                        barcode: 'somebarcode',
                        description: 'Description goes here'
                    }
                ]
            };
        }
        var config = {
            headers: { 
                'Cache-Control': 'no-cache',
                'Content-Type': 'application/json'
            }
        };
        $http.post('http://somedomain.be/trackinginfo', request, config).success(function(data, status) {
            callback(undefined, data);
        }).error(function(data, status) {
            var err = new Error('Error message');
            err.status = status;
            callback(err);
        });

ブラウザ(またはAngularJS)がそのOPTIONSリクエストを送信するのを防ぎ、実際のPOSTリクエストにスキップするにはどうすればよいですか?私はAngularJS 1.2.0を使用しています。

前もって感謝します。

80
Bram Vandewalle

プリフライトは、application/jsonのContent-Typeによってトリガーされています。これを防ぐ最も簡単な方法は、Content-Typeをtext/plainに設定することです。 application/x-www-form-urlencodedおよびmultipart/form-data Content-Typeも使用できますが、もちろんリクエストペイロードを適切にフォーマットする必要があります。

この変更を行った後もプリフライトが表示される場合は、AngularがリクエストにXヘッダーを追加している可能性があります。

または、それをトリガーするヘッダー(Authorization、Cache-Control ...)がある場合があります:

95
Ray Nicholus

Rayが言ったように、次のようにコンテンツヘッダーを変更することで停止できます。

 $http.defaults.headers.post["Content-Type"] = "text/plain";

例えば ​​-

angular.module('myApp').factory('User', ['$resource','$http',
    function($resource,$http){
        $http.defaults.headers.post["Content-Type"] = "text/plain";
        return $resource(API_ENGINE_URL+'user/:userId', {}, {
            query: {method:'GET', params:{userId:'users'}, isArray:true},
            getLoggedIn:{method:'GET'}
        });
    }]);

または直接呼び出しに-

var req = {
 method: 'POST',
 url: 'http://example.com',
 headers: {
   'Content-Type': 'text/plain'
 },
 data: { test: 'test' }
}

$http(req).then(function(){...}, function(){...});

これにより、プリフライトオプションのリクエストは送信されません。

注:リクエストにカスタムヘッダーパラメータを含めることはできません。リクエストヘッダーにカスタムヘッダーが含まれている場合、ブラウザはプリフライトリクエストを行いますが、それを避けることはできません。

13
Vivek

最善の方法は、リクエストのタイプが「OPTIONS」で、ミドルウェアから200を返すかどうかを確認することだと思います。それは私のために働いた。

express.use('*',(req,res,next) =>{
      if (req.method == "OPTIONS") {
        res.status(200);
        res.send();
      }else{
        next();
      }
    });
2

特定の種類のクロスドメインAJAXリクエストを実行する場合、CORSをサポートする最新のブラウザーは、追加の「プリフライト」リクエストを挿入して、アクションを実行する権限があるかどうかを判断します。クエリ例から:

$http.get( ‘https://example.com/api/v1/users/’ +userId,
  {params:{
           apiKey:’34d1e55e4b02e56a67b0b66’
          }
  } 
);

このフラグメントの結果、アドレスが2つのリクエスト(OPTIONSとGET)を送信されたことがわかります。サーバーからの応答には、クエリGETの許容性を確認するヘッダーが含まれます。サーバーがOPTIONS要求を適切に処理するように構成されていない場合、クライアント要求は失敗します。例えば:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept, Origin, x-requested-with, content-type
Access-Control-Allow-Methods: DELETE
Access-Control-Allow-Methods: OPTIONS
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Methods: GET
Access-Control-Allow-Methods: POST
Access-Control-Allow-Orgin: *
Access-Control-Max-Age: 172800
Allow: PUT
Allow: OPTIONS
Allow: POST
Allow: DELETE
Allow: GET
1
M.Void

プリフライトは、ブラウザによって実装されるWebセキュリティ機能です。 Chromeの場合、-disable-web-securityフラグを追加することにより、すべてのWebセキュリティを無効にできます。

例: "C:\ Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir = "C:\ newChromeSettingsWithoutSecurity"最初にクロムの新しいショートカットを作成し、そのプロパティに移動して、上記のようにターゲットを変更できます。これは役立つはずです!

0
Arijit Patra