【入門編】HTTP/1.1のExpect: 100-continueヘッダーの挙動 – HTTPプロトコル・通信規格実践ガイド

はい、承知いたしました。HTTP/1.1の`Expect: 100-continue`ヘッダーについて、インフラやネットワークの初学者の方にも分かりやすく、身近な例えを交えながら解説するブログ記事を作成します。パケットの動きや現場の知見を盛り込み、人間味あふれる温かいトーンで執筆しますね。

—

大きな荷物を送る前に、まず「大丈夫?」って確認する話 ~HTTP/1.1の`Expect: 100-continue`ヘッダー~

皆さん、こんにちは!ネットワークの広大な世界へようこそ!今日は、私たちが普段何気なく使っているWebの世界を支える、HTTPという通信のお話です。特に、ちょっとだけ「賢い」機能である`Expect: 100-continue`ヘッダーに焦点を当てて、その仕組みを紐解いていきましょう。

「`Expect: 100-continue`?なにそれ、難しそう…」と思ったあなた、大丈夫!今回は、いつも皆さんが経験しているであろう「郵便配達」に例えながら、このヘッダーがどういう役割を果たしているのか、一緒に一歩ずつ理解していきましょうね。

そもそもHTTPって、どんなお仕事?

HTTP(Hypertext Transfer Protocol)は、Webブラウザ(ChromeとかFirefoxとか)とWebサーバー(Webサイトのデータが置いてある場所)の間で、情報をやり取りするための「言葉」のようなものです。皆さんがWebサイトを見るとき、このHTTPが裏側で活躍してくれています。

このHTTPにも、バージョンがあって、私たちが今回注目するHTTP/1.1は、Webがもっともっと便利になった時代に活躍した、とっても重要なバージョンなんですよ。

大きな荷物を送る時の、ちょっとした不安…

さて、ここで想像してみてください。あなたは、とても大きな、重たい荷物を友達に送りたいとします。

1. いきなり送る?
それとも、
2. まず「この荷物、受け取ってもらえる?」って確認してから送る?

普通なら、いきなり重たい荷物を送って、もし相手が「え、そんなに重いの無理!」ってなったら、送った側もがっかり、受け取る側も困ってしまいますよね。だから、事前に「この荷物、大丈夫?」って確認してから送る方が、お互いに安心できると思うんです。

HTTPの世界でも、これと似たような状況が起こり得ます。それが、大きなリクエストボディ(送りたいデータ本体)をサーバーに送信する時です。

HTTP/1.1の「賢い」機能:`Expect: 100-continue`ヘッダー

HTTP/1.1には、この「いきなり送る前に確認する」という仕組みを実現するための、特別なヘッダーがあります。それが、今回のお題である`Expect: 100-continue`ヘッダーなんです。

`Expect: 100-continue`ヘッダーの「郵便配達」バージョン

このヘッダーが活躍する流れを、郵便配達に例えて見てみましょう。

【`Expect: 100-continue`ヘッダーがない場合】

1. あなた(クライアント): 「友達(サーバー)よ、これ、荷物(リクエストボディ)だよ!」と、いきなり大きな荷物を友達の家に届けに行きます。
2. 友達(サーバー): 荷物を受け取ってみたら、「うわ、重すぎて持てないよ…」となるかもしれません。
3. 結果: 友達は荷物を受け取れず、あなたは「あー、無駄足だった…」となります。

【`Expect: 100-continue`ヘッダーがある場合】

1. あなた(クライアント): まず、手紙(HTTPリクエストのヘッダー部分)に、「『この後、大きな荷物を送るつもりなんだけど、受け取ってくれる?』」と書いて、友達(サーバー)に送ります。

  • ここで、手紙に「`Expect: 100-continue`」と書くイメージです。

2. 友達(サーバー): 手紙を受け取ります。「なるほど、大きな荷物が来るのか。うちには置くスペースもあるし、大丈夫だよ!」と返事をします。

  • この時、友達は「`100 Continue`」(OKだよ、という意味)という返事を送り返します。

3. あなた(クライアント): 「やった!大丈夫なんだ!」と確認できたので、安心して大きな荷物(リクエストボディ)を友達(サーバー)に送ります。
4. 友達(サーバー): 荷物を受け取ります。
5. 結果: お互いに無駄なく、スムーズに荷物のやり取りができましたね!

この、最初に「`Expect: 100-continue`」と書いて「荷物送るけど、大丈夫?」と確認し、サーバーから「`100 Continue`」というOKサインをもらってから、実際に大きな荷物(リクエストボディ)を送る、という流れが、`Expect: 100-continue`ヘッダーの働きなんです。

なぜ「大きなリクエストボディ」で使うの?

「そんな確認、いつも必要なの?」と思いますよね。実は、そうではありません。

  • 小さな荷物(リクエストボディが小さい場合):

ちょっとした手紙や小さな箱くらいの荷物なら、わざわざ確認する手間よりも、いきなり送ってしまった方が早いですよね。HTTPでも、リクエストボディが小さい場合は、この確認プロセスはスキップされます。

  • 大きな荷物(リクエストボディが大きい場合):

例えば、動画ファイルや大きな画像ファイルをアップロードする時など、データ量が非常に大きい場合。もし、サーバー側がそのデータを受け取れない(例えば、ディスク容量がいっぱいだったり、リクエストサイズの上限を超えていたり)場合、クライアントは「えー!せっかく大きなデータを送ったのに、無駄になっちゃった!」ということになります。

`Expect: 100-continue`ヘッダーを使うことで、サーバー側でリクエストボディを処理する前に、事前に受け入れ可能かどうかを判断できるようになります。これにより、無駄なデータ転送を防ぎ、ネットワークリソースの節約にもつながる、というわけなんです。

実際のパケットはどう動くの?(ちょっとだけ技術的なお話)

では、この「確認」と「本送信」のやり取りが、パケットという通信の粒でどう実現されているのか、もう少しだけ深く見てみましょう。

【リクエスト側(クライアント)】

1. 最初のHTTPリクエスト(ヘッダーのみ):
クライアントは、まずHTTPリクエストのヘッダー部分だけをサーバーに送ります。このヘッダーの中に、`Expect: 100-continue`という指示が含まれています。

  • 例:

POST /upload HTTP/1.1
Host: example.com
Content-Type: image/jpeg
Content-Length: 5000000 <-- ここで、後続のボディが5MBだと伝えています Expect: 100-continue <-- 「確認してね!」という合図 2. サーバーからの応答を待つ:
クライアントは、サーバーからの返事を待ちます。
3. サーバーからの応答(`100 Continue`):
もしサーバーがリクエストを受け入れ可能であれば、`100 Continue`というステータスコード(HTTPの応答コードの一つ)を返します。

  • 例:

HTTP/1.1 100 Continue

4. 本リクエスト(ヘッダー+ボディ):
クライアントは、`100 Continue`を受け取ったら、いよいよ本番です。ヘッダーに続いて、実際に大きなリクエストボディをサーバーに送信します。
5. サーバーからの最終応答:
サーバーはリクエストボディ全体を受け取ったら、最終的な処理結果(例えば、`200 OK`や`201 Created`など)を返します。

【サーバー側】

1. リクエストヘッダーの受信:
サーバーは、クライアントから送られてきたHTTPリクエストのヘッダーを受け取ります。`Expect: 100-continue`があることに気づきます。
2. 受け入れ可否の判断:
サーバーは、リクエストボディを受け取る前に、リクエストの内容(例えば、アップロード先のディスク容量に空きがあるか、リクエストサイズの上限を超えていないかなど)をチェックします。
3. 応答(`100 Continue` または エラー):

  • 受け入れ可能な場合: `100 Continue`をクライアントに返します。
  • 受け入れ不可能な場合: `417 Expectation Failed`(期待されたものが失敗したよ、という意味)などのエラーコードを返します。この場合、クライアントはリクエストボディの送信を中止します。

4. リクエストボディの受信と処理:
`100 Continue`を受け取ったクライアントから、リクエストボディが送られてきたら、それを受け取って処理します。
5. 最終応答:
処理が完了したら、最終的なステータスコード(`200 OK`など)をクライアントに返します。

「`Expect: 100-continue`」がないと、どうなるの?

もし、`Expect: 100-continue`ヘッダーが使われなかった場合、クライアントは大きなリクエストボディをいきなりサーバーに送ってしまいます。サーバー側でリクエストボディを受け取ってみてから「あ、これ無理だった!」となると、既に送られてしまったデータは無駄になってしまいます。

この無駄をなくしてくれるのが、`Expect: 100-continue`ヘッダーの賢さなんですね。

現場でのちょっとした「あるある」

私たちが普段、Webアプリケーションの開発やサーバーの運用をしていると、この`Expect: 100-continue`ヘッダーが原因で、ちょっとしたハマりどころに遭遇することがあります。

  • 古いプロキシサーバーやロードバランサー:

HTTP/1.1の機能として登場した`Expect: 100-continue`ですが、通信経路にある古いプロキシサーバーやロードバランサーが、このヘッダーを正しく理解できずに、通信を途中で止めてしまったり、予期せぬエラーを引き起こしたりすることがあります。
「なんか特定のアップロードでだけエラーになるんだけど…」という場合、通信経路のどこかでこのヘッダーの処理に問題が起きている、なんてことも少なくないんですよ。

  • クライアント側の設定:

多くのHTTPクライアントライブラリ(例えば、Pythonの`requests`ライブラリや、JavaScriptの`fetch`APIなど)では、デフォルトで大きなボディを送信する際に、この`Expect: 100-continue`ヘッダーを自動的に付与してくれることが多いです。でも、設定によっては無効にすることもできますし、逆に意図せず有効になってしまうこともあります。
デバッグする際には、「このクライアントは、このヘッダーを付けているかな?」「サーバー側はどういう応答を返しているかな?」と確認することが、問題解決の糸口になることもあります。

まとめ:通信をもっとスマートに!

今日は、HTTP/1.1の`Expect: 100-continue`ヘッダーについて、郵便配達に例えながら解説しました。

  • 大きなデータを送る前に、サーバーに「受け取れる?」と確認するための仕組み。
  • `Expect: 100-continue`ヘッダーをクライアントが送り、サーバーが`100 Continue`で応じることで、無駄なデータ転送を防ぎます。
  • 開発や運用現場では、このヘッダーが予期せぬ挙動の原因になることもある、ちょっとした「クセモノ」でもあります。

このヘッダーの存在を知っているだけで、Web通信がどのように行われているのか、より深く理解できるようになりますし、いざという時のトラブルシューティングにも役立つはずです。

ネットワークの世界は、まだまだ奥が深いですが、こうして一つずつ仕組みを理解していくことで、皆さんのエンジニアリングの幅がぐっと広がるはずですよ!

また次回、皆さんと一緒に、ネットワークの面白い世界を覗きに行きましょう!

—

いかがでしたでしょうか。このブログ記事が、HTTPプロトコルやネットワークの理解を深める一助となれば幸いです。

コメント

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