NginxのCORS周りの設定においてリバースプロキシとして使用する場合の情報が少なかったのでメモ。
前提
サーバーの構成はこんな感じ
アプリケーションへのリクエストを捌くために、webサーバーとしてNginxを、アプリケーションサーバーとしてPumaを使っている。
アプリケーションサーバーとして何を使うかは関係なくて、とりあえずNginxがプロキシとして動いている場合を想定。
nginxのconfファイル
The way nginx and its modules work is determined in the configuration file. By default, the configuration file is named nginx.conf and placed in the directory /usr/local/nginx/conf, /etc/nginx, or /usr/local/etc/nginx.
自分の環境の場合は/etc/nginx
に設置されているようだった。
~~省略~~ http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; gzip on; gzip_http_version 1.0; gzip_proxied any; gzip_min_length 500; gzip_disable "MSIE [1-6]\."; gzip_types text/plain text/xml text/css text/comma-separated-values text/javascript application/x-javascript application/atom+xml; include /etc/nginx/mime.types; default_type application/octet-stream; include /etc/nginx/sites-enabled/*; }
見てみるとhttpディレクティブの最後にincludeディレクティブで/etc/nginx/sites-enabled/*;
とあり、こちらの設定も読み込んでいることがわかる。
デフォルトのconfファイルにはあまり細かな設定は書かずにincludeしてくるのが良いとのこと。
$ ls -ln /etc/nginx | grep sites drwxr-xr-x 2 0 0 4096 8月 13 20:42 sites-available drwxr-xr-x 2 0 0 4096 8月 5 21:11 sites-enabled
よくみると似たような名前のディレクトリがあるものの、
$ ls -ln /etc/nginx/sites-available/ 合計 12 -rw-r--r-- 1 0 0 2360 8月 13 20:42 hoge.net.conf $ ls -ln /etc/nginx/sites-enabled/ 合計 0 lrwxrwxrwx 1 0 0 35 4月 5 2018 hoge.net.conf -> ../sites-available/hoge.net.conf
片方はシンボリックリンクだった。
どうやらシンボリック側からincludeするのが通例らしい。
includeされている方のconfを見てみると
~~省略~~ server { listen 80 default_server; server_name hoge.net; # ヘルスチェック location /health { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://hoge-puma; } location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; ~中略~ proxy_pass http://hoge-puma; } # 静的ファイル location ~ ^/(img|assets|cvtest|images|uploads|javascripts|stylesheets|swfs|system)/ { gzip_static on; expires max; add_header Cache-Control public; } }
大体こんな感じ。
serverディレクティブの中でlocationディレクティブを書いている。
imageなどの静的ファイルはそのままnginxで捌いているが、アプリケーションへのリクエストはpumaに渡していることがわかる。
location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; ~中略~ proxy_pass http://hoge-puma; }
今回は特定のパスへのリクエストのみCORSの設定を追加したいので、locationディレクティブを新しく追加するか、location /
の中でif文で分岐するかのどちらかになりそう。
CORSの設定を追加
修正すべき箇所がわかったので、実際に設定を追加していく
~~省略~~ server { listen 80 default_server; server_name hoge.net; # ヘルスチェック location /health { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://hoge-puma; } location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; ~中略~ proxy_pass http://hoge-puma; } # ここに追加 location = /fuga { # CORS add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "POST, GET, OPTIONS"; add_header Access-Control-Allow-Headers "Origin, Authorization, Accept"; add_header Access-Control-Allow-Credentials true; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_hide_header 'Access-Control-Allow-Origin'; proxy_pass http://hoge-puma; } # 静的ファイル location ~ ^/(img|assets|cvtest|images|uploads|javascripts|stylesheets|swfs|system)/ { gzip_static on; expires max; add_header Cache-Control public; } }
最初に追加したヘッダは下記の4つ。
# CORS add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "POST, GET, OPTIONS"; add_header Access-Control-Allow-Headers "Origin, Authorization, Accept"; add_header Access-Control-Allow-Credentials true;
Access-Control-Allow-Origin
...CORSリクエストを許可するクライアントドメインを指定する。どこからでも許可する場合は"*"
を指定Access-Control-Allow-Methods
...CORSリクエストを許可するHTTPメソッドを指定。OPTIONSについてはプリフライトリクエストに対応
で、一度ここまで設定しただけで検証したところエラーが消えず困っていたところ、
proxy_hide_header 'Access-Control-Allow-Origin';
こちらも必要みたいだった。
参考
NGINX Reverse Proxy and Access-Control-Allow-Origin issue - Stack Overflow