0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

モノレポ構成でつまづいたリバースプロキシとCORSの問題

Last updated at Posted at 2024-12-12

1. はじめに

モノレポ構成(フロントエンドとバックエンドを一つのリポジトリで管理する形)でアプリケーションを開発していたら、「APIとフロントエンドの連携がうまくいかない」という問題が発生しました。
検索してもうまく記事を見つけられず解決まで時間がかかったので、この記事が誰かの助けになれば嬉しいです。

2. 問題の現象

2.1 発生した問題

  1. メールリンクが動作しない
    • devise_token_authによるパスワードリセットメールに記載されたリンクをクリックするとHTTP 500エラーが発生。登録認証メールも同様。
  2. Cookieが正しく付与されない
    • 認証後にセッションが保持されず、パスワードリセット画面に遷移せず。(パスワードリセット画面はCookieにトークンが付与されていないと遷移できない設定にしていた)
  3. フロントエンドがAPIレスポンスを受け取れない
    • /api/経由でリクエストを送っているはずが、フロントエンドのHTMLが返される。

2.2 デバッグで判明したこと

  • リバースプロキシ設定が不十分
    フロントエンド(www.example.com)からバックエンド(api.example.com)へのリクエストが正しくルーティングされていなかった。
  • CORSやCookieの設定が複雑化
    不適切なCORS設定やリバースプロキシの欠如が原因で、APIへの通信が正常に行われていなかった。

3. 原因の分析

今回の問題は主に以下の構成要因によるものでした:

  1. モノレポ構成によるドメイン間通信

    • フロントエンドとバックエンドが異なるドメイン(www.example.comapi.example.com)で動作。
    • ドメイン間通信にはCORSやCookieの正確な設定が必要。
  2. リバースプロキシ設定が未実装

    • フロントエンドが/api/リクエストをバックエンドに正しく転送していなかった。
  3. ヘルスチェック設定の見落とし

    • AWS ALB(ロードバランサー)のヘルスチェックパスが正しく設定されておらず、デプロイ時にロールバックが発生。

4. 解決方法

4.1 リバースプロキシ設定の実装

  • 目的
    フロントエンドの/api/リクエストをバックエンドに正確に転送。
  • 解決策:Vercelのvercel.jsonファイルに設定
    {
      "rewrites": [
        {
          "source": "/api/(.*)",
          "destination": "https://api.example.com/api/$1"
        },
        {
          "source": "/(.*)",
          "destination": "/index.html"
        }
      ]
    }
    
  • ポイント
    • source/api/をバックエンドにリダイレクト。
    • 順序が重要。/api/ルートを最初に評価することで、APIリクエストが静的ファイルに吸収されないように。

4.2 CORS設定の最適化

  • Rails APIでのCORS設定
  Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    if Rails.env.production?
      origins "https://api.example.com", 
              "https://www.example.com", 
              "https://example.vercel.app",
              /https:\/\/.*\.vercel\.app/ # Vercelのすべてのサブドメインを許可
    else
      origins "http://localhost:5173"  # 開発用
    end
    resource "*",
      headers: :any,
      methods: %i[get post put patch delete options head],
      credentials: true,
      expose: ["access-token", "expiry", "token-type", "uid", "client"]
  end
end
  • 改善点
    • 許可するドメイン(www.example.comapi.example.com、Vercelのサブドメイン)を設定。
    • Cookieを利用するためcredentials: trueを指定。

4.3 ALBのヘルスチェック設定

  • ヘルスチェックパスを明確に
    • ALBでの設定:
      パス: /health_check
      ポート: トラフィックポート
      成功コード: 200-399
      
    • Railsで以下の設定を追加:
      config.host_authorization = { exclude: ->(request) { request.path == "/health_check" } }
      

5. 検証手順

以下のコマンドで動作を確認:

  1. リバースプロキシの確認

    curl -X GET -v https://www.example.com/api/v1/sessions
    
    • 正しいレスポンス(ステータス200)が返ることを確認。
  2. メールリンクの確認

    • パスワードリセットメールから送信されるリンクをクリックして、期待通りのページが表示されることを確認。

6. 学んだこと

  1. モノレポ構成の課題
    • フロントエンドとバックエンドが分離した環境ではリバースプロキシ設定が重要。
  2. CORSの本番環境設定
    • 開発環境で問題なく動いていても、本番環境用のCORSやCookie設定が必要。

7. リバースプロキシのまとめ

リバースプロキシとは、クライアント(ユーザー)からのリクエストを受け取り、適切なサーバーに転送する役割を持つサーバーや仕組みのことです。

  • ロードバランシング:複数のバックエンドサーバーにリクエストを分散させ、負荷を均等にします。
  • セキュリティ強化:バックエンドサーバーを直接公開せず、リバースプロキシを介してアクセスさせることで、セキュリティを向上。
  • リクエストルーティング:クライアントからのリクエストを適切なバックエンドサービスに振り分けます。

今回のケースでは、Vercelのリバースプロキシ設定を使い、/api/に送られたリクエストをRails APIサーバーに転送するようにしました。これにより、フロントエンドとバックエンドの分離環境で通信が行えるようになりました。

もし同じような問題に直面している方がいたら、この記事が参考になれば幸いです。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?