Skip to content

HTTP Request

Min edited this page Dec 31, 2023 · 8 revisions

POST /cgi-bin/submit_form.cgi HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

name=John+Doe&email=john@example.com

構成要素

  1. リクエストライン
  2. ヘッダー
  3. ボディ

1. リクエストライン

POST /cgi-bin/submit_form.cgi HTTP/1.1

[method] [target] [version] "\r\n"

method

実行するアクションを表わす動詞 (GETPUTPOST など) または名詞 (HEAD、OPTIONS)。例えば GET はリソースを取り込むこと、POST はデータをサーバーへ送信すること (リソースを作成または変更する、あるいは返送する一時的なドキュメントを生成する) ことを示します。 要請メソッドは、 文字大小区別。

※今回は、GET, POST, DELETEのみ。

target

通常は URLですが、プロトコル、ポート番号、ドメインの絶対パスは通常、リクエストの状況から明らかにされます。リクエスト対象の形式は、HTTP メソッドにより異なります。以下のような形式があります。

  • 最後に '?' とクエリー文字列がある絶対パス。これはオリジン形式とも呼ばれているもっとも一般的な形式であり、GET、POST、HEAD、OPTIONS メソッドで使用します。
    • POST / HTTP/1.1
    • GET /background.png HTTP/1.0
    • HEAD /test.html?query=alibaba HTTP/1.1
    • OPTIONS /anypage.html HTTP/1.0
  • 完全な URL は絶対形式とも呼ばれ、主にプロキシーへ接続する際に GET で使用します。 GET https://developer.mozilla.org/ja/docs/Web/HTTP/Messages HTTP/1.1
  • ドメイン名とポート(省略可能。':' を前につける)で構成される、URL の authority の部分は認証形式と呼ばれます。これは CONNECT で HTTP トンネルを設定するときに限り使用されます。CONNECT developer.mozilla.org:80 HTTP/1.1
  • 単純なアスタリスク ('*') であるアスタリスク形式は OPTIONS で使用され、サーバー全体を表します。 OPTIONS * HTTP/1.1

※今回、取り消し線は非対応でok。

version

HTTP バージョン。これはメッセージの残りの部分の構造を定義しており、レスポンスで使用することを想定しているバージョンを示す役割もあります。

※今回は、HTTP/1.1だけ対応でいいかも?

2. ヘッダー

Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

大文字・小文字を区別しない文字列の後にコロン (':') と、ヘッダーに応じた構造の値が続きます。値を含むヘッダー全体は 1 行で構成されており、とても長くなる場合もあります。(Nginxでは、8192 byte以上はエラーとなる。) 特定のフィールドライン値内の内容は、メッセージ解釈の後期段階まで解析されません。

  • リクエストヘッダー
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br

User-Agent, Accept などで、指定するとリクエストを変更するもの(Accept-Language など)、状況を示すもの(Referer など)、条件を制約するもの(If-None など)があります。

  • 一般ヘッダー

Connection: keep-alive

メッセージ全体に適用されるもの。

  • 表現ヘッダー

Content-Length: 36

Content-Type など、メッセージデータの下の形式や適用されているエンコーディングを説明します(メッセージの本体がある場合のみ存在します)。

本体は、大きく 2 種類に分類される。

3. ボディ

name=John+Doe&email=john@example.com

リクエストの最後の部分が本体 (body) です。本体が存在しないリクエストもある。GET, HEAD, DELETE, OPTIONS は、ボディは不要。今回は、POSTメソッドでのみ必要となる(HTMLフォームのデータ)。

パースについて

データ構造

struct ParsedRequest
{
	const std::string				method;
	const std::string				uri;
	const std::string				version;
	const std::map<std::string, std::string>	header;
	const std::string				body;

	ParsedRequest(const std::string &m, const std::string &u, const std::string &v, const std::map<std::string, std::string> &h, const std::string &b) 
			: method(m), uri(u), version(v), header(h), body(b) {}
};

パース方法

1. リクエストライン

堅牢性のために、リクエストラインを受信して解析することを期待しているサーバーは、リクエストラインの前に少なくとも1つの空の行(CRLF)を無視する必要があります。

始めの空行はwhileで飛ばす。 8192文字を超えたら、414エラー。

メソッド

confから使用可能なメソッドを確認する必要あるのかもしれない(今後confの意味を把握したときにわかると思われる)。 GET, POST, DELETE以外は405エラーを出している。

ターゲット

CONNECTメソッドに対応する必要がないので、:があるときは400エラー。 OPTIONSメソッドに対応する必要がないので、*も同様。

バージョン

HTTP/1.1以外の文字列は400エラー。

2. ヘッダー

1行につき、8192文字を超えたら、414エラー。

3. ボディ

  • chunk方式

チャンク方式を使えば、検索やライブ配信などで効率的な転送ができる。 チャンクのサイズを逐次取得し、そのサイズ分読み込む。

7
Mozilla
9
Developer
7
Network
0
  • それ以外

課題要件

• 少なくともGET、POST、DELETEのメソッドが必要です。

参考