263
247

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-02-11

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

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

263
247
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
263
247

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?