日別アーカイブ: 2022年11月4日

VueとRailsで作成したアプリで得た知見と備忘録4(AxiosとCORS)

3から続いています

目標:すぐに思い出せるようにざっくり解説する。

流れ

  1. フロントエンドからサーバーサイドのリクエスト用にAxiosを設定します。
  2. サーバーサイドでリクエストを受け入れられる用にCORSの設定をします。
  3. TODOの登録のリクエストを送り、保存されるか確認します。

前提知識

Axiosとは?

フロントエンドからバックエンドにリクエストを送るときに使っていくライブラリで
ブラウザやNode.js上で動くPromiseベースのHTTPクライアントです。

Promiseとは

JavaScriptの非同期処理の完了もしくは失敗を表すオブジェクトで、
非同期処理が完了したときに結果を返してくれます。

HTTPクライアントとは

GET・POST・PATCHなどのHTTPリクエストを送信して、
そのレスポンスを受信できるものです。

Axiosを利用するJavaScript非同期処理を行う際にHTTPリクエスト送って、レスポンス返してもらい、何らかの処理行うことができるようになります。

4章:APIの連携をする

1:フロントからサーバーサイドのリクエスト用にaxiosを設定する

Axiosの設定:baseURLの設定

baseURLは環境変数を設定することで設定できます。
Nuxt.jsで環境変数を扱う際は@nuxtjs/dotenvというライブラリを入れます。

frontのディレクトリで行います。

npm install --save-dev @nuxtjs/dotenv

front/nuxt.config.jsにbuildModulesという部分があるので、そこに追記します。

'@nuxtjs/dotenv', // 追記

.envを以下のような階層構造で作成します。

nuxt-rails-todo
├── api
└── front
  └── .env

そして以下のように記述します。

API_ENDPOINT="http://localhost:3000"

Railsはサーバーを起動すると、デフォルトでポート3000が使用されるためです。

Nuxtでもポート3000を使っているため衝突してしまいます。

front/nuxt.config.jsを変更することでNuxt側を変更します。

front/nuxt.config.js

import colors from 'vuetify/es5/util/colors'

export default {
 server: {
  port: 8080 
},

これで、npm run devを実行すると、8080番ポートが使用され、
Railsと同じポートでぶつかることもなくなります。

npm run devを実行して、http://localhost:8080/にアクセスして、
ToDoの一覧画面が出ればOKです。

2:サーバーサイドでリクエストを受け入れられるようにCORSの設定をする

CORSとは?

Cross-origin Resource Sharingの略称(オリジン間のリソース共有)

役割は同一オリジンポリシー(Same-Origin Policy)というルールによって
設けられた制限を緩めるものです。

同一制限ポリシーとは?

同一オリジンポリシーとは、ウェブブラウザに設けられた、
セキュリティ攻撃などの防止のための仕組みです。
異なるオリジン間のリソースへのアクセスに制約をかけるものです。

オリジンとは、URIのスキーム、ホスト、ポート番号の組み合わせのことです。

例えば、http://localhost:3000というURIがあったときに、オリジンは以下のように分解できます。

http: スキーム
localhost: ホスト
3000: ポート番号

異なるオリジン間でリソースにアクセスしようとした時に、ウェブブラウザが制限をかけてくれる仕組みのことです。

CORSは何のために設定する?

同一オリジンポリシーというルールによって設けられた制限を緩めるためで
作成しているアプリは、フロントエンドバックエンドが分かれています。
フロントエンドからバックエンドへ何かリクエストを行うと、この同一制限ポリシーに引っかかってしまい、アプリが意図したように動作しなくなってしまいます。
そのため、CORSという部分的に同一オリジンポリシーを解除する設定をしてあげる必要があります。

3:RailsAPIでのCORS設定方法

Gemのインストール

RailsでCORSを許可するために必要なGemを入れていきます。

デフォルトでコメントアウトされているので、それを外します。

api/Gemfile

# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
gem 'rack-cors'

以下のコマンドでインストールします

cd ../api
bundle install

4:CORSの設定ファイルの編集

api/config/initializers/cors.rbで以下のように記述します。

#コメントアウトを外して8080にする
Rails.application.config.middleware.insert_before 0, Rack::Cors do
 allow do
  origins 'localhost:8080' 

  resource '*',
 headers: :any,
 methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end

5:Nuxt側のリクエスト部分を修正する

front/pages/index.vueを開いて、<script>の中に以下のコードを追加します。

front/pages/index.vueのスクリプト部分から追記
<script>
  import AddTodo from "@/components/AddTodo";
  import TodoList from "@/components/TodoList";
  import axios from "@/plugins/axios";  // サーバーサイドにHTTPリクエストをするために、axiosを追加

  export default {
    components: {
      AddTodo,
      TodoList,
    },
    data() {
      return {
        todos: [],
      };
    },
    methods: {
      async addTodo(title) { // フロントエンドの処理を動かしつつ、サーバーサイドでもToDoの登録を行いたいため、非同期でサーバーサイドにリクエストを送る
        await axios.post("/v1/todos", { title }); // awaitで下の処理が先に実行されるのを防ぐ。
        this.todos.push({
          title
        });
      },
    },
  };
</script>

↑のasyncawaitは作成ボタンを押したら、先にサーバーサイド側でToDoを登録する処理を確実に行いたいためです。

axios.post("/v1/todos", { title });

↑ではTODOのタイトルを値として、サーバーサイド(API)のv1/todosというURLにPOSTリクエストが送信できるようにしています。

その5に続く