LoginSignup
3
2

More than 1 year has passed since last update.

nginxのCORS問題を解決する

Last updated at Posted at 2023-04-04

localhostでの制作tipsは山ほど出てきたけど
探し方が良くないのかlocalhost-サーバ間の情報って全然見つからない。

構成

key value
用途 APIサーバ
インスタンス AWS EC2
SSL LetsEncrypt (Certbot)
Webサーバ nginx
App実行環境 node.js
フレームワーク express (3000番ポートで稼働)
DB MongoDB

nginxのリバースプロキシ,CORS設定

localhost⇔サーバ
サーバ⇔サーバ
におけるnginxの設定は以下で動くのを確認。

    map $http_origin $cors{
        "^http://localhost(:\d+)?" $http_origin;
        "^https://chirimen-jako.com" $http_origin;
    }

    server {
        if ($host = api.chirimen-jako.com) {
            return 301 https://$host$request_uri;
        } # managed by Certbot

        listen       80;
        listen       [::]:80;
        server_name  api.chirimen-jako.com;
        return 404; # managed by Certbot
    }

    server {
        server_name  api.chirimen-jako.com;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
            location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }

        listen [::]:443 ssl ipv6only=on; # managed by Certbot
        listen 443 ssl; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/api.chirimen-jako.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/api.chirimen-jako.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

        location / {
            add_header Access-Control-Allow-Origin $cors always;
            add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;
            add_header Access-Control-Allow-Headers 'X-Requested-With,Accept,Content-Type, Origin' always;

            proxy_pass http://localhost:3000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }

(たぶんを含む)解説

mapディレクティブ

    map $http_origin $cors{
        "^http://localhost(:\d+)?" $http_origin;
        "^https://chirimen-jako.com" $http_origin;
    }

$cors変数に2種類のoriginをマッピングしている。
if文でlocalhostかサーバか振り分けようとしたがnginxのif文はルールが特殊過ぎてヤバいとのことなのでmapで解決。
機能的に仕様通りではあるがプログラマが通常考えるif文とは違うので..らしい。
参考サイト

serverディレクティブ(:80)

  server {
        if ($host = api.chirimen-jako.com) {
            return 301 https://$host$request_uri;
        } # managed by Certbot

        listen       80;
        listen       [::]:80;
        server_name  api.chirimen-jako.com;
        return 404; # managed by Certbot
    }

httpでアクセスがあった場合はs付けてリダイレクト。
SSLを当てる時にCertbotが大体勝手に設定してくれる。

serverディレクティブ(:443)

    server {
        server_name  api.chirimen-jako.com;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
            location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }

        listen [::]:443 ssl ipv6only=on; # managed by Certbot
        listen 443 ssl; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/api.chirimen-jako.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/api.chirimen-jako.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

        location / {
            add_header Access-Control-Allow-Origin $cors always;
            add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;
            add_header Access-Control-Allow-Headers 'X-Requested-With,Accept,Content-Type, Origin' always;

            proxy_pass http://localhost:3000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }

locationディレクティブまではほぼデフォルトなので省略。
「# managed by〜」の箇所もCertbotの仕事。
proxy云々の箇所は3000番ポートのアクセスをnodejs(express)へ中継している。
add_headerでレスポンスヘッダにCORS周りの設定を追加している。
ステータスコードが20x/30x系レスポンス以外はadd_headerが効かないとのことなので
alwaysパラメータを付与して必ずヘッダに入るように設定。

おわり。

3
2
0

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
3
2