LaravelでCORS対応

アプリケーション

概要

LaravelでCORS(Cross-Origin Resource Sharing)に対応する方法をまとめました。
クライアントサイドはReact, axiosを使用します。
前提知識としては、CORSのリクエスト形態、シンプルなリクエスト方法と、preflightを使用するリクエスト方法の違いを抑えておけば良いかと思います。
RESTfulAPIの場合は基本的にはpreflightを使用するリクエスト形式かと思います。
この記事では、preflightを使用するリクエストに対応する例を取り上げます。

環境

CORSなので当たり前ですが、apiとwebでドメインを用意しています。

api.hogehogedomainadmin.hogehogedomainみたいな感じでドメインが用意されていて、adminの方から別ドメインで管理されているAPIをコールする、といった感じです。

Middlewareを用意する

APIを提供している側、Laravel側でAPIリクエスト時にヘッダ情報を調整するmiddlewareを用意します。

と、ここで自作のミドルウェアを作成したかったのですが、何故か更新系のメソッドだけ上手く動作しなかったので、barryvdh/laravel-corsを使うことにします。

セットアップはREADME通りです。

composer require barryvdh/laravel-cors

config/app.phpのprovider配列に以下を指定
Barryvdh\Cors\ServiceProvider::class,

app/Http/Kernel.phpのapiミドルウェアグループにcorsミドルウェアを設定

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
            \Barryvdh\Cors\HandleCors::class, // <-Here!
        ],
    ];

設定ファイルをパブリッシュして編集。
php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"

config/cors.php

return [
     /*
     |--------------------------------------------------------------------------
     | Laravel CORS
     |--------------------------------------------------------------------------
     |
     | allowedOrigins, allowedHeaders and allowedMethods can be set to array('*')
     | to accept any value.
     |
     */
    'supportsCredentials' => true, // change false to true !
    'allowedOrigins' => ['*'],
    'allowedHeaders' => ['Content-Type', 'X-Requested-With'],
    'allowedMethods' => ['*'], // ex: ['GET', 'POST', 'PUT',  'DELETE']
    'exposedHeaders' => [],
    'maxAge' => 0,
]

クッキーの送信およびBasic認証の許可しておきたいので、 supportsCredentialstrueにしておきます。

サーバー側の設定は以上です。

クライアントサイドからAPIをコールしてみる

axiosでヘッダ情報の定義をしておきます。

action/index.js

const api = axios.create({
  baseURL: 'http://api.rubel/v1',
  timeout: 10000,
  headers: {
    'X-Requested-With': 'XMLHttpRequest'
  }
});

export function createCategory(props) {
  const request = api.post(`/categories`, props);

  return {type: CREATE_CATEGORY, payload: request};
}

クライアント側では、X-Requested-Withヘッダをセットするだけで、後は普通にapiを叩くだけです。

所感

自作ミドルウェアがなぜ上手くいかなかったのか解決できていないので消化不良ですが、一旦はこれで問題ないでしょう。。

参考


関連書籍