【Nuxt3×Rails7】API通信を行ってみよう

運営者:そうすけ


愛媛出身の30代のブロガー兼ソフトウェアエンジニア
主にフロント・バックの開発を行っています。

趣味はガジェットと植物

目次

フロントとバックで通信するときには設定が必要

RailsとNuxtで通信するのは異なるオリジン間の通信とになるのでCORS設定をしないといけません。

CORS設定を行う

CORSとは、オリジン間リソース共有(Cross-Origin Resource Sharing)の略で、異なるオリジン間でデータや画像、およびスクリプトファイルなどを共有する仕組みです。

通常ブラウザでは異なるオリジン間の通信は規約違反になっており、設定をしないとデータを共有することができません。

そもそもオリジンとはなんでしょう。

オリジンとは?

ウェブコンテンツのオリジン (Origin) は、ウェブコンテンツにアクセスするために使われる URL の スキーム (プロトコル)、 ホスト (ドメイン)、 ポート番号 によって定義されます。スキーム、ホスト、ポート番号がすべて一致した場合のみ、 2 つのオブジェクトは同じオリジンであると言えます。

https://developer.mozilla.org/ja/docs/Glossary/Origin

CORSについてはこのブログで丁寧に説明されていました。

方法

railsにrack.corsというGemをインストールする

クロスオリジン間の制約を設定してくるrack-corsをインストールします。

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

config\initializers\cors.rbができているので、ファイルを設定します。

この設定を行うことで、RailsのレスポンスのヘッダにAccess-Control-Allow-Originの値が付与されて、クロスオリジン操作ができるようになります。

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "ここにFrontのオリジン名(localhost:3000 など)"

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

私も詳しくはないですが、許可するオリジンの他に、許可するリクエストメソッド、Cookie情報の許可など、このGemがその辺の設定を定義してくれます。

CORSのレスポンスヘッダについてはこちらが詳しかったです。

今回はNuxt3側は通信するのみなのであれば設定はいりません。

api通信してみる

userと表示させるApiを作ってみます。

rails g controller Api::V1::user
class Api::V1::UserController < ApplicationController
    def index
        render json: "user"
    end
end
Rails.application.routes.draw do
   # 追加
  namespace :api do
    namespace :v1 do
      # api test action
      resources :user only:[:index]     
    end
  end
end

フロントは$Fetchを使用します

<template>

  <div>{{users}}</div>

</template>
  
  <script setup lang="ts">
  //環境変数を取得
  const config = useRuntimeConfig()
  const users = ref<string[]>("")
  async function getHello(){
    //先にユーザーを用意
    const { data } = await useFetch(config.public.apiOrigin+'/api/v1/users')
 //ENVファイルの環境変数使っているがhttp://localhost:3000でもいい
    users.value = data.value    
    console.log(data)
  </script>
  

デベロッパーツールのNetworkタブのHeadersを見てみると、リクエストのヘッダに実際に乗っていることがわかります。

リクエストのヘッダー情報にX-Requested-With: ‘XMLHttpRequest’をいれる

CSRF対策になります。

class ApplicationController < ActionController::API

     # CSRF対策
    before_action :xhr_request?

    private

    # XMLHttpRequestでない場合は403エラーを返す
    def xhr_request?
    # リクエストヘッダ X-Requested-With: 'XMLHttpRequest' の存在を判定
    return if request.xhr?
    render status: :forbidden, json: { status: 403, error: "Forbidden" }
    end

end
<template>

  <div>{{users}}</div>

</template>
  
  <script setup lang="ts">
  //環境変数を取得
  const config = useRuntimeConfig()
  const users = ref<string[]>("")
  async function getHello(){
    //先にユーザーを用意
    const { data } = await useFetch(config.public.apiOrigin+'/api/v1/users',
                     headers:{
                       'X-Requested-With': 'XMLHttpRequest',                        
                      }  )
 //ENVファイルの環境変数使っているがhttp://localhost:3000でもいい
    users.value = data.value    
    console.log(data)
  </script>
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

目次