概要
前回の記事ではRailsを使って、APIの受け側を作りました。
ただ、このままだとJSでフロントエンドからAPIに対してリクエストした場合、preflightリクエストが飛ぶので、No route matches [OPTIONS]
エラーが返ってしまい、正常終了できません。
今回は、Railsでpreflightリクエストを処理し、no route matches optionsを回避する方法を書きます。
処理の方針
fetch("http://localhost:3000/auth_user", { method: 'POST', body: JSON.stringify({ emai: "emai@email.com", password: "********"}) }).then(function(response) { return response.json(); }).then(function(json) { ... });
こんな感じでフロントからリクエストをすることを想定します。
fetchでリクエストする場合、クロスドメインアクセスが可能か確認するするため、OPTIONSリクエストを飛ばして、それが200になってから本来のリクエストを飛ばします。
また、preflightリクエストが成功にするには、2つ条件があります。
- OPTIONSをルーティングできること
- response.headersに適切なキーとバリューが設定されていること
今回は、上記2つの条件を満たすための処理を書くことを目標にします。
OPTIONSをルーティングできること
乱暴ではありますが、いかなるpathのリクエストに対してもOPTIONSリクエストであれば、response.headersの設定を行えるようにします。 config/routes.rbに下記を追加しましょう。
match '*path' => 'options_request#preflight', via: :options
今回はoptions_request_controller.rbを作成して、そこで処理をすることにします。
response.headersに適切なキーとバリューが設定されていること
ルーティングファイルに従って、options_request_controller.rbを作成します。 また、response.headersに適切なキーとバリューが設定しなければならないので、このように処理をします。
class OptionsRequestController < ApplicationController ACCESS_CONTROL_ALLOW_METHODS = %w[GET OPTIONS PUT DELETE POST].freeze ACCESS_CONTROL_ALLOW_HEADERS = %w[Accept Origin Content-Type Authorization].freeze ACCESS_CONTROL_MAX_AGE = 86_400 protect_from_forgery except: :preflight before_action :set_preflight_headers!, only: [:preflight] def preflight response.headers['Access-Control-Max-Age'] = ACCESS_CONTROL_MAX_AGE response.headers['Access-Control-Allow-Headers'] = ACCESS_CONTROL_ALLOW_HEADERS.join(',') response.headers['Access-Control-Allow-Methods'] = ACCESS_CONTROL_ALLOW_METHODS.join(',') response.headers['Access-Control-Allow-Origin'] = '*' head :ok end end
こちらの処理の通り、response.headers
の中にいくつかキーとバリューを設定しています。
レスポンスヘッダーの詳細説明に関しては、こちらの記事に譲るとして、やっていることをざっくり説明するとこのようになります
キー | バリュー | 意味 |
---|---|---|
Access-Control-Max-Age | 86400 | preflightリクエストの結果を24時間キャッシュ |
Access-Control-Allow-Headers | Accept,Origin,Content-Type,Authorization | リクエスト時にどのヘッダーが使用可能か明示 |
Access-Control-Allow-Methods | GET,OPTIONS,PUT,DELETE,POST | リソースのアクセス時に許容するメソッドを明示 |
Access-Control-Allow-Origin | * | 許容できるアクセス元のURLを明示 |
まとめ
今回、とりあえずハマりを抜け出すために、簡易な処理を書きましたが、要点としては下記2点です。
- OPTIONSリクエストを受け付けるようにする
- 受け付けたOPTIONSリクエストのレスポンスに
Access-Control-Allow-ほげほげ
をつける
SPAでAPI連携をするときにハマりポイントではありますし、何回作っても毎度ハマるので参考にしていただければと思います