タイトルは釣り、かつ、自分のための備忘録です。
マイクロサービスアーキテクチャでサービスを構築すると、APIサーバをサービスごとに立てるわけですが、
ブラウザ上のJSエンジンからAPIサーバを叩く時に避けて通れないのが、Same-Origin Policy(同一生成元ポリシー)
によるCORS (Cross-Origin Resource Sharing)
制限です。
これを回避するには、APIサーバ側でAccess-Control-*
ヘッダを適切に返す必要がありますが、どう設定するべきかの情報が意外と少ないので(自分的)これが決定版! という設定を考えてみました。
結論
nginxの場合の設定例です。
server {
listen 80;
server_name site.localhost;
charset utf-8;
root /var/www/app/public;
location / {
# preflightに対するレスポンス指定
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin '*';
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE';
add_header Access-Control-Allow-Headers 'Origin, Authorization, Accept, Content-Type';
add_header Access-Control-Max-Age 3600;
add_header Content-Type 'text/plain charset=UTF-8';
add_header Content-Length 0;
return 204;
}
try_files $uri /index.php?$query_string;
}
location ~ \.php$ {
# alwaysオプションを付けて、常にヘッダが出力されるようにする
add_header Access-Control-Allow-Origin '*' always;
fastcgi_pass localhost:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
ブラウザ上のJSエンジンは、APIサーバ(別ドメイン)にリクエストを投げる前にOPTIONS
メソッドによるアクセスを行います。
これはAccess-Control-*
情報を問い合わせるためのpreflight
と呼ばれるアクセスです。
if($request_method = 'OPTIONS'){ 〜 }
は、このpreflightに対するレスポンスを定義しています。
(レスポンスボディは特に無いので、204: No Response
を返す。)
ヘッダ | 値 |
---|---|
Access-Control-Allow-Origin | アクセスを許可するOriginのURL。"*"で指定なし。 |
Access-Control-Allow-Methods | 使用可能なメソッド |
Access-Control-Allow-Headers | 使用可能なリクエストヘッダ |
Access-Control-Max-Age | preflightの結果をキャッシュしても良い時間(秒) |
実際の本アクセスの場合もAccess-Control-Allow-Origin
ヘッダが無いと、JSエンジンがレスポンスをブロックしてしまいますので指定が必要です。
ただし、nginxの場合デフォルトでは(200系、300系の)特定レスポンスコード以外の場合はヘッダの追加をスキップしてしまうので(参考)、400系のエラーを返す場合に対応できるようにalways
指定が必要になります。