JavaScript
nginx
Ajax
CORS

APIサーバを立てるためのCORS設定決定版

More than 1 year has passed since last update.

タイトルは釣り、かつ、自分のための備忘録です。

マイクロサービスアーキテクチャでサービスを構築すると、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指定が必要になります。