【実務・中級編】HTTP/1.1のメソッド:OPTIONSの役割 – HTTPプロトコル・通信規格実践ガイド

なぜ今さら「OPTIONS」なのか?――Web API開発者が知っておくべきプリフライトの真実

ネットワークエンジニアとして現場を長く歩いていると、「GETやPOSTはわかるけど、OPTIONSって何のためにあるの? 使わなくても動くよね?」という若手エンジニアからの質問をよく耳にします。

確かに、ブラウザで適当なURLを叩いてもOPTIONSメソッドが返ってくることは稀ですし、通常のWeb閲覧で意識することはまずありません。しかし、現代のAPIファーストな開発環境において、OPTIONSを理解していないことは「見えない場所で発生している通信エラーの正体を掴めない」と言っているのと同じです。

今日は、HTTP/1.1の仕様の隅っこでひっそりと、しかし極めて重要な役割を担う「OPTIONSメソッド」の正体を、現場の視点から解き明かしていきましょう。

—

1. OPTIONSメソッドの本質:サーバーとの「事前交渉」

RFC 7231に定められたOPTIONSメソッドの本来の役割は、「そのリソースに対して、どのようなメソッド(GET, POST, PUT, DELETE等)が実行可能なのかを確認すること」です。

サーバーに対し `OPTIONS ` を投げればサーバー全体の能力がわかり、特定のリソースに対して投げれば「君、ここはPATCHは受け付けてくれるの?」といった確認ができます。しかし、実務においてこの「能力確認」のためにOPTIONSを使うことはほとんどありません。

現在、我々がOPTIONSに遭遇するほとんどのケースは、「CORS(Cross-Origin Resource Sharing)のプリフライトリクエスト」です。

なぜプリフライトが必要なのか

ブラウザはセキュリティの観点から、異なるオリジン(ドメインやポート)へのリクエストを厳格に制限します。例えば、`frontend.com` から `api.backend.com` に対して、認証ヘッダーを付与したPUTリクエストを送ろうとした場合、ブラウザは「いきなり危険なリクエストを投げてサーバーを壊さないか?」と疑います。

そこで、メインのリクエストを送る前に、ブラウザが勝手に「これからこのリクエストを送るけど、許可してくれる?」とOPTIONSで伺いを立てる。これがプリフライトの正体です。

—

2. 通信フロー:プリフライトの裏側

実際の通信シーケンスは以下のようになります。

1. ブラウザ (OPTIONS送信): 「PUTを送りたいんだけど、このヘッダー(Authorization)を付けてもいい? 許可してくれよ」
2. サーバー (200 OK + Header): 「いいよ。許可するメソッドはPUTで、許可するヘッダーはAuthorizationだ。有効期限は1時間ね」
3. ブラウザ (本来のリクエスト送信): 「OK、じゃあPUTを送るよ」

このステップ2でサーバーが適切なレスポンスを返せないと、ブラウザは「CORSエラー」を吐いてメインリクエストを断固として送信しません。

—

3. 実践:デバッグと設定の勘所

現場でよくあるのが、「curlで叩くと成功するのに、ブラウザからだとエラーになる」という相談です。これは間違いなくCORS設定、つまりOPTIONSメソッドへのレスポンスが不適切であるケースがほとんどです。

curlでOPTIONSを確認する

まずは現状把握です。ブラウザを介さず、サーバーが何と答えるかを確認しましょう。

-X OPTIONSでメソッドを指定
-v でレスポンスヘッダーを確認
curl -X OPTIONS -I -H “Origin: https://frontend.com” \
-H “Access-Control-Request-Method: PUT” \
https://api.backend.com/resource

ここで `Access-Control-Allow-Origin` や `Access-Control-Allow-Methods` が正しく返ってきているか確認してください。

Nginxでの設定例

リバースプロキシ層でCORSを制御する場合、Nginxの設定はこうなります。

location /api/ {
# プリフライトリクエスト(OPTIONS)を即座に204で返す
if ($request_method = ‘OPTIONS’) {
add_header ‘Access-Control-Allow-Origin’ ‘https://frontend.com’;
add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, PUT, OPTIONS’;
add_header ‘Access-Control-Allow-Headers’ ‘Authorization, Content-Type’;
# プリフライト結果をキャッシュさせる秒数(無駄な通信を減らす)
add_header ‘Access-Control-Max-Age’ 3600;
add_header ‘Content-Type’ ‘text/plain charset=UTF-8’;
add_header ‘Content-Length’ 0;
return 204;
}

# メインのリクエストに対するヘッダーも忘れずに
add_header ‘Access-Control-Allow-Origin’ ‘https://frontend.com’;
proxy_pass http://backend_upstream;
}

—

4. エンジニアへのアドバイス:無駄なプリフライトを避ける

最後に、インフラ設計者としてのアドバイスです。OPTIONSリクエストは、メインのリクエストの前に必ず発生するため、APIのレスポンス速度に直接影響を与えます。

  • Access-Control-Max-Age を活用する:

一度許可したプリフライト結果をブラウザ側にキャッシュさせます。これを適切に設定しないと、APIを叩くたびに往復のネットワーク通信が発生し、モバイル環境などでは明確な体感遅延となります。

  • シンプルなリクエストを心がける:

実は、特定の条件(Content-Typeが `application/x-www-form-urlencoded` など)を満たす「単純なリクエスト」であれば、プリフライトは発生しません。JSONを投げるAPIが主流の今、ほぼ全ての通信でプリフライトが発生しますが、「なぜ今この通信が重いのか?」というボトルネック調査の際、このOPTIONSの往復を忘れないでください。

OPTIONSメソッドは、単なる「おまけ」のメソッドではありません。クライアントとサーバーの信頼関係を構築するための、Webというプラットフォームの「握手」そのものなのです。

トラブルシューティングの際、ブラウザのコンソールだけで悩むのではなく、ぜひネットワークパケットのレベルまで視点を下げてみてください。そこに必ず答えはあります。

コメント

タイトルとURLをコピーしました