1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OPTIONS リクエスト(クロスオリジンプリフライト)

Posted at

背景

最近、私は個人ブログサイトを開発しています。小規模なプログラムなので、バックエンドには Node.js と Express フレームワークを使用し、フロントエンドには Vue 3、データベースには SQLite を選びました。

まずはデータベースとバックエンドプログラムを書き終え、PostMan で API のテストを行い、すべて正常に動作しました。

デバッグを簡単にするため、バックエンドに GET リクエストを受け取るテスト API を作成し、フロントエンドのセットアップ後にバックエンドと接続してテストしましたが、問題なく動作しました。

その後、ログイン API の接続を試みましたが、POST リクエストがバックエンドに届かないという問題が発生しました。

原因を調べてみると、どうやらバックエンドの CORS 設定に問題があったようです。設定を修正した後、無事解決しました。

image-20250204155324493.png
image-20250204155336116.png

さらに考えたこと

ところで、OPTIONS リクエストとは一体何なのでしょうか?もし設定を間違えた場合、なぜ GET テスト API は正常に動作するのでしょうか?

調べた結果得られた答え

1. OPTIONS リクエストとは?

OPTIONS リクエストは、HTTP プロトコルの一つで、サーバーがサポートする HTTP メソッドを取得するために使用されます。

  • OPTIONS リクエストはブラウザの挙動であり、クロスオリジン(CORS)リクエストが行われる際、ブラウザは予め OPTIONS リクエストを送信してサーバーが対応可能なメソッドを確認します。
  • 一般的に、AJAX リクエストにのみ制限がかかり、linkimgscriptiframe のようなリクエストには制限はありません。
  • サーバー間でのクロスオリジンリクエストでは、OPTIONS リクエストは発生しません。
    image-20250204161901725.png

OPTIONS リクエストの特徴:

  • リクエストボディはありません;
  • レスポンスボディもありません;
  • セキュア;
  • 冪等性(同じリクエストを何度送っても結果が変わりません);
  • キャッシュできません;
  • フォーム内で使用できません。

2. シンプルリクエストと複雑リクエスト

CORS の予備チェックリクエスト(OPTIONS)を発生させないリクエストを「シンプルリクエスト」、予備チェックを発生させるリクエストを「複雑リクエスト」と呼びます。

シンプルリクエスト:

(次のすべての条件を満たす場合)

  • リクエストメソッド: GET、HEAD、POST。

  • 許可されたヘッダーのみ使用:AcceptAccept-LanguageContent-LanguageContent-Type など。

  • Content-Type の値が次のいずれかの場合:application/x-www-form-urlencodedmultipart/form-datatext/plain

    ※例えば、POST リクエストで Content-Type: application/json やトークン系のヘッダーを使用すると、OPTIONS リクエストが発生します。

    ※フロントエンドで axios を使用して POST リクエストを送信する際、JavaScript オブジェクトを直接渡すと、axios は自動的にそれを JSON 文字列にシリアライズし、リクエストヘッダーの Content-Typeapplication/json;charset=UTF-8 に設定します。(これも私のプログラムで問題が発生した理由です)

複雑リクエスト:

(次のいずれかを満たす場合)

  • リクエストメソッド:PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH。
  • シンプルリクエスト以外のヘッダーを設定した場合。
  • Content-Type の値が次のいずれかに該当しない場合:application/x-www-form-urlencodedmultipart/form-datatext/plain

3. 特定のリクエストヘッダー、レスポンスヘッダー

特定のリクエストヘッダー:

  • Access-Control-Request-Method: 実際のリクエストで使用するメソッド(例:GETPOST)をサーバーに通知。 例:Access-Control-Request-Method: GET
  • Access-Control-Request-Headers: 実際のリクエストで送信するカスタムリクエストヘッダーをサーバーに通知。 例:Access-Control-Request-Headers: token

特定のレスポンスヘッダー:

  • Access-Control-Allow-Methods: クライアントが使用できるメソッド。 例:Access-Control-Allow-Methods: PUT
  • Access-Control-Allow-Origin: 許可されたオリジン。すべてのオリジンを許可するには * を設定。 例:Access-Control-Allow-Origin: http://localhost:8080
  • Access-Control-Allow-Headers: 許可されたリクエストヘッダー。 例:Access-Control-Allow-Headers: token, Origin
  • Access-Control-Allow-Credentials: クッキーを送信するかどうか。 例:Access-Control-Allow-Credentials: true
  • Access-Control-Max-Age: 予備チェックリクエスト(OPTIONS)の結果をキャッシュする期間。 例:Access-Control-Max-Age: 60(1分以内は再度 OPTIONS リクエストが発生しない)

以上です。お読みいただきありがとうございました。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?