君は心理学者なのか?

大学時代に心理学を専攻しなぜかプログラマになった、サイコ(心理学)プログラマかろてんの雑記。

【nginx】status codeが400系/500系の時に限り、CORSエラー(Origin http://xxxxxx is not allowed by Access-Control-Allow-Origin)が出る

f:id:karoten512:20190829214411p:plain

背景

静的サイト(originサーバがドメインA)からAPIドメインB)へアクセスする、

いわゆるCORSの仕組みを使ったAPI通信をしていた。

CORSを実現するため、nginxの設定ファイルには以下のように記述をしていた。

    location / {
      add_header Access-Control-Allow-Origin "domain A";

      # OPTIONS(priflight request)用の設定
      if ($request_method = OPTIONS ) {
        add_header Access-Control-Allow-Origin "domain A";
        return 200;
      }
    }

※ めっちゃ略してます

現象

POST, PUTの成功時(status code 200)の時は特に問題ないが、

失敗時(status code 400, 500系)のときに

Origin http://domainA is not allowed by Access-Control-Allow-Origin

とコンソールに表示され、ブラウザがresponseの結果を受け取ってくれない。

curlで叩いた時のresponse headerを見ると、

確かにAccess-Control-Allow-Origin headerが付与されていない。

調査結果

    location / {
      add_header Access-Control-Allow-Origin "domain A";
    }

上記の記述だと、

status codeが200系、300系のときしかheaderが追加されないことがわかった。

Adds the specified field to a response header provided
that the response code equals 
200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13), or 308 (1.13.0).
Parameter value can contain variables.

nginx公式ページより

よって400, 500系の結果がかえってきた時、

responseにAccess-Control-Allow-Origin headerが付与されていないため、

ブラウザはそのresponseを取得してくれない。

解決策

    location / {
      add_header Access-Control-Allow-Origin "domain A" always;
    }

上記のように、alwaysを追記する。

そうすることにより、status codeによらずheaderが追加される。

If the always parameter is specified (1.7.5),
the header field will be added regardless of the response code.

nginx公式ページより

結果

400, 500系でもCORSエラーが起きなくなった。