CORS対策にハマりたくなかったために、Laravelに同一オリジン(いわゆるモノレポ)構成でフロント環境を構築したはずなのに、下記のエラーが出まくり。
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の翻訳機能でサクッと日本語変換できちゃいます。
コメント