経緯
最近「実装で学ぶフルスタックWeb開発 エンジニアの視野と知識を広げる「一気通貫」型ハンズオン」という本で勉強をしています。
※第2版です。
途中までしか読んでいないものの、とてもいい本で勉強になります。
ただ、本日「4-2-2 フロントエンドからバックエンドのAPIを呼び出す」の部分で嵌ってしまいましたので、ここに対応メモを残しておきます。
エラー内容
初回レンダリング後にNext.jsのフロントエンドからDjangoのバックエンドのAPIが呼び出され、「hello」の後の表示が変わるはずが、画像のようにエラーになり、表示が変わらない。
原因と対処
ポートの指定をする
フロントエンドはlocalhost:3000で動作しているのに対し、バックエンドはloalhost:8000で動作しています。
フロントエンドから単にAPIを呼び出すと、localhost:3000にアクセスしてしまいエラーになりますので、アクセスするポートを明示的に指定します。
フロントエンドのhello_backend/page.tsx でaxiosをインポートした次の行で設定をすればよいです。
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:8000' //これを追加!
※Copilotに聞いたところ、axiosのインスタンスを作ってそっちの設定を変える方法もあるらしいです。
CORS設定を変える
上記によってHTTP応答のステータスは200 OKとなりますが、実際にはコンテンツを読み込むことができず依然としてエラーのままになります。
これは、CORS(Cross Origin Resource Sharing)設定が原因です。
※Cross Origin Resource Sharing とは、別オリジンからのコンテンツを利用するかどうか決めたりします。 これがないと意図せず無関係のサーバにデータを送らせるような処理を実行してしまったりと、XSS(クロスサイトスクリプティング)やCSRF(クロスサイトリクエストフォージェリ)に弱くなってしまったりするそうです。
※今回は同じlocalhostに対するアクセスですが、アクセスするポートが違うので別オリジン扱いとなります。
対処法としては、以下をすればよいです。
(1) CORS関係のライブラリを入れる。
pip install django-cors-headers
(2) Djangoの設定ファイル(base.py)でライブラリをインストールしてミドルウェアとして指定するように追記する。
INSTALLED_APPS = [
'corsheaders',
//~中略~
]
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
//以下略
(3) 同じくbase.pyでCORSの設定変更をするように追記する。
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
]
感想
Qiita 初投稿でしたので大変でした。。
間違いなどありましたらフィードバックもらえると嬉しいです。
参考リンク