13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Nuxt.js × Railsでアプリ作成 CORS policy エラーの解決

Posted at

やりたいこと

  • Railsで作ったAPIに対してNuxt.js側から投稿する(前回の記事の続編です)

開発環境

ruby 2.6.5
Rails 6.0.3.4
node v14.7.0
yarn 1.22.4
フロント(Nuxt.js)のローカルサーバーのport番号は8000
API(Rails)のローカルサーバーのport番号は3000

投稿画面のマークアップ

  • sendボタンがクリックされたら、Postmanで投稿ができることを確認できたURI http://localhost:3000/api/v1/postsPOSTリクエスト を送るような処理を実装

app.gif

pages/index.vue
<template>
  <div class="container">
    <h4>新規投稿</h4>
    <div class="form-control">
      <span>Title</span>
      <input
        type="text"
        v-model="title"
      >
    </div>
    <div class="form-control">
      <span>Body</span>
      <input
        type="text"
        v-model="body"
      >
    </div>
    <div class="form-control">
      <button @click="postMessage">send</button>
    </div>
  </div>
</template>

<script>
export default {
  data: () => ({
    title: null,
    body: null,
  }),
  methods: {
    postMessage() {
      const url = 'http://localhost:3000/api/v1/posts';
      const post = {
        title: this.title,
        body: this.body,
      };
      this.$axios.post(url, { post })
        .then(res => console.log(res.status))
        .catch(error => console.log(error));
    },
  }
}
</script>

<style>
.container {
  width: 60%;
  max-width: 600px;
  margin: 0 auto;
}
.form-control {
  margin: 20px 0;
}
h4 {
  text-align: center;
}
span {
  width: 4em;
  display: inline-block;
}
input[type="text"] {
  width: calc(100% - 6em);
}
button {
  margin: auto;
  display: block;
}
</style>

CORSでのエラーになる時の解決方法

  • 上記で実装すると、console.logに下記が出力される

Access to XMLHttpRequest at 'http://localhost:3000/' from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

なぜ正しくリクエストが送れていないのか?
結論
Nuxt側(フロント側)からそのままURIを指定してしまうと CORSの制限がかかっているため 正しくリクエストが送れていない

CORSとは

オリジン間リソース共有Cross-Origin Resource Sharing (CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。
ウェブアプリケーションは、自分とは異なるオリジン (ドメイン、プロトコル、ポート番号) にあるリソースをリクエストするとき、オリジン間 HTTP リクエストを実行します。

MDNより抜粋

CORS (オリジン間リソース共有) の問題を解決する

Nuxt公式ページに書いてある方法をそのまま実施します
※ 公式ページではnpmでインストールしていますが、今回はyarnで開発しているので下記コマンドを使います(npmやyarnのコマンドについてはこちらも参照ください)

// @nuxtjs/proxyのインストール
$ yarn add @nuxtjs/proxy
app/nuxt.config.js
modules: [
  '@nuxtjs/axios',
  '@nuxtjs/proxy'
],
proxy: {
  '/api': {
    target: 'http://localhost:3000',
    pathRewrite: {
      '^/api' : '/api/v1'
    }
  }
},

pathRewrite'^/api' : '/api/v1' の記述は、 @nuxtjs/proxyのgithubを参考にしています

上記では、vue側でリクエストとして指定している /api がつく接頭辞を /api/v1 にリライト(書き換え)て、http://localhost:3000 に送ってね、と指定しています

proxyやpathRewriteについての記述方法はこのサイトも参考になりました

Nuxt側の修正

上記でProxyを設定してCORSの問題を解決する設定をしたので、NuxtのファイルでリクエストをPOSTしている箇所を修正します

pages/index.vue
// 上の部分は省略
  methods: {
    postMessage() {
      const url = '/api/posts';
      const post = {
        title: this.title,
        body: this.body,
      };
      this.$axios.post(url, { post })
        .then(res => console.log(res.status))
        .catch(error => console.log(error));
    },
  }
// 以下省略

const url = '/api/posts'; と訂正する
※ Proxyの設定、pathRewriteの設定により、http://localhost:3000/api/v1/posts にリクエストして、と変換される

Rails側の修正

api/app/controllers/api/v1/posts_controller.rb
# 上の部分は省略
  private

  def set_post
    @post = Post.find(params[:id])
  end

  def post_params
    params.require(:post).permit(:title, :body)
  end
end

送られてくるパラメーターは、Nuxt側でこのようなオブジェクト型で指定しているため、require(:post)をする必要がある

pages/index.vue
const post = {
  title: this.title,
  body: this.body,
};

※このオブジェクト名がhogeだったら、require(:hoge)となる

13
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?