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を使用しています。
前もって感謝します。
プリフライトは、application/json
のContent-Typeによってトリガーされています。これを防ぐ最も簡単な方法は、Content-Typeをtext/plain
に設定することです。 application/x-www-form-urlencoded
およびmultipart/form-data
Content-Typeも使用できますが、もちろんリクエストペイロードを適切にフォーマットする必要があります。
この変更を行った後もプリフライトが表示される場合は、AngularがリクエストにXヘッダーを追加している可能性があります。
または、それをトリガーするヘッダー(Authorization、Cache-Control ...)がある場合があります:
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(){...});
これにより、プリフライトオプションのリクエストは送信されません。
注:リクエストにカスタムヘッダーパラメータを含めることはできません。リクエストヘッダーにカスタムヘッダーが含まれている場合、ブラウザはプリフライトリクエストを行いますが、それを避けることはできません。
最善の方法は、リクエストのタイプが「OPTIONS」で、ミドルウェアから200を返すかどうかを確認することだと思います。それは私のために働いた。
express.use('*',(req,res,next) =>{
if (req.method == "OPTIONS") {
res.status(200);
res.send();
}else{
next();
}
});
特定の種類のクロスドメイン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
プリフライトは、ブラウザによって実装されるWebセキュリティ機能です。 Chromeの場合、-disable-web-securityフラグを追加することにより、すべてのWebセキュリティを無効にできます。
例: "C:\ Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir = "C:\ newChromeSettingsWithoutSecurity"最初にクロムの新しいショートカットを作成し、そのプロパティに移動して、上記のようにターゲットを変更できます。これは役立つはずです!