production環境は同一サーバー、development環境だと別々で、フロントはJSのサーバー(ポート番号が違う)という環境は、昨今のSPAを開発するときにあるあるな環境だと思います。
JSONでやり取りをするときに、production環境だと普通にうまくいくのに、developmentだとポート番号が違うためクロスドメインになるという感じでエラー。
ここで一旦Railsであれこれやってドハマリ。解決してみれば超簡単だったのでメモしておきます。
現状僕の場合、フロントのファイルを更新したら即反映されるBrowserSyncやHot Reloadがない環境なしではやってられないぐらいなので、ここを解決することで非常にスムーズに開発することができました。
##クロスドメインだとPOSTがOPTIONSになる
クロスドメインでPOSTすると最近だとOPTIONSに変換されるということを知りました。
じゃあ最初にヘッダーにCORSを許容するドメインとかの設定をして、ルーティングでOPTIONSの設定をして…みたいなことをして時間をくってハマっていたのですが、そんなことをしなくてもすんなり解決する方法があったのでした…
サーバー側の解決策
gemを追加し、反映させるだけでした。
https://github.com/cyu/rack-cors
group :development, :test do
gem 'rack-cors', :require => 'rack/cors'
end
上記記述後、bundle install
# developmentモードの時だけCORSを有効にする
if Rails.env.development?
config.middleware.insert_before ActionDispatch::Static, Rack::Cors do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options, :patch, :delete]
end
end
end
上記設定だけでバックエンドにおけるCORSの設定は終わりです。
APIファーストでバックエンドとフロントエンドを別々に開発する時にハマるクロスドメインアクセス
クロスドメインについては上記投稿が参考になります!
フロント側の解決策
今回の場合、ログインした後にJSでAPIをGET・POSTしたかったため、Cookieを送ってあげる必要がありました。
Cookieを適切に送ってあげるような設定でない場合、サーバー側で適切に処理されていれば401(Unauthorized)エラーが発生し、で何が何でもAPIにアクセスすることができません。
withCredentials
CORSで通信し、かつCookieなどの情報をやり取りする場合、withCredentialsをtrueにしてあげないと適切に処理が行えません。
今回はフロントにvue、Ajax通信にvue-resourceを使用したので下記のようなコードを書くことでポート番号がバラバラなサーバーでもクロスドメインで通信することができました。
this.$http({
params: params,
url: URL,
method: 'POST',
credentials: true
})
.then(
(response)=> {
// success
console.log(response);
},
(response)=> {
// error
console.log("error");
console.log(response);
}
);
※上記はdevelopmentの時に用いる設定になります。
おわりに
Railsで開発する場合、だいたいGemが揃っているのでやはり強いなーという感じ。自分で書くと大変でしたが、ライブラリを用いるとbundle installの時間のほうが掛かりました。
やはり過去の資産があり、それが現在でもちゃんと使えるということは強みだなと認識しました。