「No 'Access-Control-Allow-Origin'」が出た時に疑うこと・解決策リスト

# 普段の環境
・Vue CLI（4系）
・Laravel（6系）
・XAMPP
・Vue ⇔ Laravel間はaxiosを使用


# 疑うこと・解決策リスト

### 1. レスポンスヘッダーに「Access-Control-Allow-~~~」を入れているか

Vue.jsとLaravelなどで開発を行う場合、フロントエンド・バックエンドのドメインが異なる場合もあるかと思います。
（例えば、Vue.js→「[http://localhost:8080](http://localhost:8080)」、Laravel→「[http://localhost:8001](http://localhost:8001)」など）
この場合、axiosなどで普通に通信しようとすると、タイトルのCORSエラーが出るので、レスポンスヘッダー（バックエンド側）で、下記のような記述をしてあげましょう。

```php
header('Access-Control-Allow-Origin: http://localhost:8080'); // ←アクセスを許可したいドメインを設定
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, PATCH');
header('Access-Control-Allow-Headers: Content-Type');
```

Laravelの場合、下記のようなMiddlewareを作って、ミドルウェアに設定をしてあげるとよいです。

```AccessControlAllow.php
<?php

namespace App\Http\Middleware\Api;

use Closure;

class AccessControlAllow
{
    public function handle($request, Closure $next)
    {
        return $next($request)
            ->header('Access-Control-Allow-Origin', 'http://localhost:8080') // ←アクセスを許可したいドメインを設定
            ->header('Access-Control-Allow-Credentials', 'true')
            ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH')
            ->header('Access-Control-Allow-Headers', 'Content-Type');
    }
}
```

### 2. リクエストしているURLが存在しているか

よくあるのが、タイポ（タイプミス）で、存在しないURLにアクセスしている場合です。
この場合も、タイトルの「No 'Access-Control-Allow-Origin'～」エラーが発生することがあります。

下記は「/api/contact/send-mail」とするところを、「/api/contct/send-mail」と打ち間違えた例。

```typo.js
const formData = new FormData();
formData.append("contact_data", JSON.stringify(this.contactData));
this.$axios
  .post(`/api/contct/send-mail`, formData) // ← タイポ！
  .then((response) => {
    console.log(response);
    if (response.data.status === 200) {
      alert("送信しました？");
      return;
    } else {
      alert("エラーが発生しました。");
      return;
    }
  })
  .catch((err) => {
    console.log(err);
  });
```


### 3. キャッシュを削除してみる

以前、これに数時間悩まされました。

例えば、上の「2.」で示したようにタイポで一度「No 'Access-Control-Allow-Origin'～」エラーを出してしまうと、問題箇所をいくら直しても同じエラーが出続けることがあります。

こんな時はどこが悪いのかそれ以上深追いせずに、一度キャッシュを全消去してみましょう。

やり方はChromeの場合、

① 履歴を表示。（Windowsの場合、ショートカットキーは「Ctrl + H」）
② 「閲覧履歴データの削除」
③ 「全期間」を選択、全部チェックで「データを削除」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2532969/ed9580a1-8865-44fb-7136-e989e636c0cc.png)

これであっさり直るかも？


### 4. フロントエンド側のProxyを使ってみる

フロントエンド側にProxy機能があるのなら、それを使ってみるのも一手です。

CORSは要は、
・「a.com」⇔「b.com」
のように、ドメインが違う通信を行おうとすることでエラーが出ます。

これを、Proxy（代理機能）を使用することで、ドメインを偽装することができます。

つまり、Proxyが間に入って、
・「a.com」→「b.com（Proxyで偽装）」⇔「b.com」
という通信になることで、CORSエラーを回避します。

Vue.jsの場合、Proxyの設定は[こちら](https://qiita.com/yusuke5/items/00ec8c773ded292478ec)を参考に。


### 5. axiosの「axios.default.withCridentials」設定を行っているか

フロントエンドとバックエンドの通信をaxiosで行っている場合、
「axios.default.withCridentials = true;」の設定をしていないと、
「No 'Access-Control-Allow-Origin' ～ 」エラーが出ることがあります。

Vue.jsの場合、こんな感じ。

```main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
//
import axios from 'axios'
//

// グローバル登録（axiosを使う時はいつでも「axios.defaults.withCredentials = true;」）
axios.defaults.withCredentials = true; // ← ココ
axios.defaults.xsrfHeaderName = "X-CSRF-Token";
//

//
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')
```

# CORSはつらいよ

また異なるケースが出れば追加していきます。