【解決済】Docker上のNuxtでaxiosのCORSエラーにハマりまくった話

CORS対策にハマりたくなかったために、Laravelに同一オリジン(いわゆるモノレポ)構成でフロント環境を構築したはずなのに、下記のエラーが出まくり。

Access to XMLHttpRequest at ‘http://localhost:8000/api/store/income’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

Laravel(API) × Nuxtで、axiosでのAPI通信時のCORSエラーへの対処法はググれはいくらでも出てくる。

が、、、、どれをやってもダメ。

今回は”Docker上のコンテナ”ということがネックだったみたい。「やはり環境が違えば、解決方法も違うのか・・・」とどっと疲れましたorz

実行環境:

  • Linuxサーバー上のDocker on Ubuntu 20.04
  • Laravel 6.20(ホスト0.0.0.0 port8000)
  • Nuxt 2.15.3(ホスト0.0.0.0 port3000)
  • @nuxtjs/axios 5.13.1
目次

解決策:CORSエラーはaxiosの設定が原因だった

今回のCORSエラーの原因はaxiosの設定だった!!

以下、解決時に追記したnuxt.config.jsの一部

 axios: {
    proxy: true,
    baseURL: 'http://localhost:8000/api/',
  },

  proxy: {
    '/api/': {
      target: 'http://localhost:8000',
    },
  },

調べると

  • axiosにproxy設定すればいい
  • laravelにCORS設定が必要

など出てきますが、どれも「あと一歩!」というところでCORSエラーが解決しません。

色々やっていくうちに、Docker環境では、axiosの設定に「baseURL、browserBaseURL」の記述が必要との記事を見つけ、トライしてみた所うまくいきました。

nuxt/axiosドキュメントによると、

baseURLとは

サーバー側の要求を行うために使用および追加されるベースURLを定義します

browserBaseURLとは

クライアント側の要求を行うために使用および付加されるベースURLを定義します(デフォルト:baseURL)

とのことで、baseURLとbrowserBaseURLが同じURLの場合はbaseURLだけの記載で良いこともわかりました。やはり公式ドキュメントは熟読すべし!!!

proxyの設定入れるだけでは解決しないんですね・・・

ちなみに今回の環境(モノレポ環境)ではlaravelにCORS対策のミドルウェアを書いたり、という設定は不要でした。(一応書いてみたけど、解決後に消しても動いているので、laravel側の設定は不要かと)

解決の手順

あくまでも「別サーバー内のDockerにubuntuコンテナ立てて外からSSHした場合」の対処ですが、以下の手順でaxiosのCORSエラーが解決できました。

nuxt.config.jsの編集だけでなく、フロント側のAPI呼び出し方法も記述が変わることがミソです。

1.nuxt.config.jsの編集

最終的なnuxt.config.jsはこうなりました。

modules: [
    '@nuxtjs/axios',
  ],

  axios: {
    proxy: true,
    baseURL: 'http://localhost:8000/api/',
  },

  proxy: {
    '/api/': {
      target: 'http://localhost:8000',
    },
  },

@nuxtjs/proxyモジュールのインストールは必要ありません。

実運用ではURLなどは環境変数に外出しし、env等で読み込んで秘匿性を高めるのだと思います。

3.API呼び出し処理の変更

methods: {
    async store() {
      const url = `/api/store` //ここ重要
      const data = {
        message: this.message,
        price: this.price,
        remark: this.remark,
      }
      await axios.post(url, data)
    },
  },

axiosで叩くAPIのURLは、通常下記のようにフルパスで書くと思いますが、

const url = `http://localhost:8000/api/store`

今回はnuxt.config.jsにproxyの設定を入れているので、/apiからのパスを書きます。

const url = `http://localhost:8000/api/store`

この書き方に変更しないとCORSエラーが出続けるので注意。

これで、axiosによりしっかりAPIが叩けるでしょう!!お疲れ様でしたm(_ _)m

asyncDataではCORSエラーが出ない不思議・・・

ちなみに、、、

nuxtの便利メソッドasyncDataを使ったAPI通信では、proxy設定など入れずともCORSエラーは起きませんでした。

asyncDataはレンダリング前に読み込む処理が走るメソッドで、CORSに関係なくAPIが叩けるんでしょうかね〜。ホント謎仕様です^^

export default {
  async asyncData({ $axios }) {
    const res = await $axios.$get('http://localhost:8000/api/getall')
    const incomeTotal = res[0].reduce(function (sum, element) {
      return sum + element.price
    }, 0)
 }
}

参考になった記事

思考の葉 Nuxt.jsで@nuxtjs/proxyを利用する [CORS][Axios]

stack overflow Docker RailsのCORS設定について

nuxt/axios公式ドキュメント options

まとめ

「モノレポ構成でのWebアプリ開発は、CORSエラーに悩まされることは無い」と高を括っていたものの、axiosの仕様でやられました。

nuxtもその辺は”うまいこと”やれるような仕様になっているらしく、nuxt.config.jsへの簡単な追記のみでaxios通信時のCORSエラーは回避できました。

まぁこの情報にたどり着くまで1週間悩んだんですが、、、公式ドキュメントはよく読め!!ってことですね。最近は翻訳の精度も高いので、日本語版が出ていない公式サイトもchromeの翻訳機能でサクッと日本語変換できちゃいます。

よかったらシェアしてね!

コメント

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

目次
閉じる