web-dev-qa-db-ja.com

Angular $ httpはPUT / POSTではなくOPTIONSを送信しています

PHPバックエンドを介してMySQLデータベースのデータを更新/挿入しようとしています。 AngularJSを使用してフロントエンドを構築し、REST AP​​Iとの通信に$httpサービスを使用しています。

私のセットアップは次のようになります。

$ httpProvider:経由でヘッダーを設定しています

 $httpProvider.defaults.withCredentials = true;
 $httpProvider.defaults.headers = {'Content-Type': 'application/json;charset=utf-8'};

そしてPOST-Callは次のようになります:

   return $http({
      url: url,
      method: "POST",
      data: campaign
    });

ChromeのDev Consoleにこれが表示されます:

enter image description here

POSTからPUTに変更すると、PUTで​​はなくOPTIONS呼び出しを送信します。そして、content-typeはcontent-typeのみに切り替わります。

私の要求ペイロードはオブジェクトとして送信されます:

enter image description here

ヘッダーを適切に設定するにはどうすればよいですか?


編集:

PHPバックエンドはいくつかのヘッダーを設定します:

   $e->getResponse()
              ->getHeaders()
              ->addHeaderLine('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');

   $e->getResponse()
              ->getHeaders()
              ->addHeaderLine('Access-Control-Allow-Origin', '*');

何か足りないものはありますか?

61
Bastian Gruber

はい、解決しました。

問題は何でしたか?
DELETE、PUT、およびPOSTのCORSワークフローは次のとおりです。

enter image description here

それは何ですか:

  1. どのリクエストが行われるかを確認する
  2. POST、PUT、またはDELETEの場合
  3. 最初にOPTION要求を送信して、要求の送信元のドメインがサーバーからのドメインと同じかどうかを確認します。
  4. ない場合、Access-Headerにこのリクエストの送信を許可します

ここで重要:OPTIONSリクエストは資格情報を送信しません

そのため、バックエンドサーバーはPUT要求を許可しませんでした。

解決策:
これを.htaccessファイル内に配置します

RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ blank.php [QSA,L]
Header set Access-Control-Allow-Origin "http://sub.domain:3000"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"

この後、blank.phpという空の.phpファイルをパブリックフォルダー内に作成します。

編集:1人のコメンターが指摘したように、空のPHPファイルを作成する代わりに、この書き換えルールを.htaccessファイルに追加できます。

RewriteRule ^(.*)$ $1 [R=200,L,E=HTTP_Origin:%{HTTP:Origin}]]

明確にするために:

  1. 既にAccess-Control-Headerを送信しました
  2. それが解決したのは最初の2行で、
  3. ポートを持つ特定のサブドメインからのAccess-Control-Allow-Origin

私が見つけることができる最高のウェブサイト CORSの詳細

71
Bastian Gruber

$httpヘッダーを手動で指定する必要はありません。すべてが舞台裏で行われ、POSTおよびPUTタイプのリクエストに対して自動的にapplication/jsonに設定されます。だからあなたがすべきことはすべて

$http.post(url, data);
$http.put(url, data);
4
Dan Moldovan