参考にさせていただいたページ
fetchの第一引数について
CORSの設定について
はじめに
今回の私のポイントとしては以下のようなことでした。
- fetchの第一引数にはどういうURL文字列を渡したら良いか
- RailsのCORSの設定をどうやったら良いか
frontend/pages/index.tsxにgetStaticProps()を定義する
frontend/pages/index.tsxに以下の通り、getStaticProps()を定義して、Homeコンポーネントでpropsを受け取るようにしました。
〜略〜
export const getStaticProps = async () => {
const response = await fetch('http://nginx:8000/api/tasks');
const json = await response.json();
return {
props: json,
};
};
const Home: NextPage = (props) => {
console.log(props);
〜略〜
}
export default Home
fetchの第一引数は "http://[サービス名]:[ポート番号]/api/tasks"
みたいな感じで渡すと大丈夫でした。
rails/Gemfileの編集
以下の行を追記しました。
gem 'rack-cors'
bundle install
% docker-compose run --rm app bundle install
build
Gemfileを編集したのでbuildし直します。
% docker-compose build
rails/config/initializers/cors.rbの作成とその記述内容
% vim rails/config/initializers/cors.rb
以下の通り記述しました。
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "*"
resource "*",
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
rails/config/environments/development.rbの編集
rails/config/environments/development.rbのendの内側の一番下にconfig.hosts << "nginx"
と一行追記しました。
以下のようになります。
require "active_support/core_ext/integer/time"
Rails.application.configure do
〜略〜
# localhost:ポート番号では通信に失敗します。
# fetchの引数に渡しているサービス名と合わせます。
config.hosts << "nginx"
end
docker-compose restartする
railsのconfigを変更したので、設定反映のためにrestartします。
% docker-compose restart
ブラウザで確認してみる
以下の「httpのURL」と「httpsのURL」にブラウザでアクセスして、ブラウザのコンソールでpropsが確認できました。
rails/config/initializers/cors.rbを少し修正する
originsはワイルドカードじゃない方が良いと思うので、以下の通り修正します。
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '127.0.0.1:3000', 'localhost:3000'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
ブラウザで確認してみる
一度restartします。
% docker-compose restart
以下の「httpのURL」と「httpsのURL」にブラウザでアクセスして、ブラウザのコンソールでpropsが確認できたら完成かなと思います。
railsアプリケーションの「タスクの新規登録」が動かなくなっていたので直す
だいぶ後になってわかったことですが、CORSを設定したことによって動かなくなっていたようです。
大事なのでここに追記しておきます。
「タスクの新規登録」ページからPOSTすると以下のエラーが出るようになりました。
ActionController::InvalidAuthenticityToken (HTTP Origin header (https://web-bonsai.com) didn't match request.base_url (http://web-bonsai.com)):
「【Rails/Nginx/ELB 】ActionController::InvalidAuthenticityToken HTTP Origin header (https://example.com) didn’t match request.base_url (http://example.com)の解決法|Rubinistを目指す新米エンジニアのTECH BLOG」を参考にさせていただいて解決しました。
以下の行を追記します。
proxy_set_header X-Forwarded-SSL on;
おまけ
上手くいかない場合1
Uncaught FetchError: request to http://localhost:8000/api/tasks failed, reason: connect ECONNREFUSED 127.0.0.1:8000
のようなエラーが表示されて上手くいかない場合は、fetchの第一引数が適切でないかもしれません。
上手くいかない場合2
FetchError: invalid json response body at http://nginx:8000/api/tasks reason: Unexpected token < in JSON at position 0
のようなエラーが表示されて上手くいかない場合は、以下のようにgetStaticPropsの中で console.log(response)
して、responseを確認してみると良いと思います。
export const getStaticProps = async () => {
const response = await fetch('http://nginx:8000/api/tasks');
console.log('==============================')
console.log(response)
console.log('==============================')
const json = await response.json();
return {
props: json,
};
};
ターミナルを見ると以下のように403エラーが出力されていると思います。
==============================
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: {
body: PassThrough {
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: true,
[Symbol(kCapture)]: false,
[Symbol(kCallback)]: null
},
disturbed: false,
error: null
},
[Symbol(Response internals)]: {
url: 'http://nginx:8000/api/tasks',
status: 403,
statusText: 'Forbidden',
headers: Headers { [Symbol(map)]: [Object: null prototype] },
counter: 0
}
}
==============================
そんなときはRailsのCORSの設定が上手くいっていないとか、docker-compose restartを忘れてるのかもしれません。