CGIメモ - JUNNETWORKS/42-webserv GitHub Wiki

CGIスクリプトの出力をどのようにクライアントにHTTPレスポンスとして返すか

CGIスクリプトの出力に Content-Length ヘッダーが含まれていた場合はそのヘッダーをそのままHTTPレスポンスのヘッダーに搭載して返す。

Content-Length に基づき受信するバイト数を制限するのはクライアント側の仕事であり、サーバーはすべてのボディをHTTPレスポンスとして送り続ける(Apacheの仕様)。 ただし、これだとCGIスクリプトが永遠に完了しない場合にプロセスが増え続けるので、webserv側でCGIスクリプトの実行時間のタイムアウト(30秒)を設定する(Apacheの仕様)。

Content-Length ヘッダーが無い時は chunked 通信にして、 CGIレスポンスボディをHTTPレスポンスボディとして返す。 すべてのCGIスクリプトの出力が読み取り終わったら 0 (チャンク通信の終わり) を返す。

実際のボディが Content-Length を超えている場合

curl では Content-Length がHTTPレスポンスで指定されているのにも関わらず、それ以上のデータの受信を検知した場合、HTTP/1.1 (Connection: Keep-Alive) だとしてもソケット接続を切断する。

文字コードについて

CGIスクリプトに渡すメタ変数(環境変数)の値には拡張ASCIIコード(ISO-8859-1)を利用するっぽい?

Character set The US-ASCII character set [9], excluding NUL, is used for the definition of meta-variables, header fields and CHAR values; TEXT values use ISO-8859-1. The PATH_TRANSLATED value can contain any 8-bit byte except NUL. The newline (NL) sequence is LF; servers should also accept CR LF as a newline.

RFC3975 7.2 UNIX

HTTPでやり取りするときのパス上でのパーセントエンコーディングはUTF-8に従うらしい。

When a new URI scheme defines a component that represents textual data consisting of characters from the Universal Character Set [UCS], the data should first be encoded as octets according to the UTF-8 character encoding [STD63]; then only those octets that do not correspond to characters in the unreserved set should be percent- encoded. For example, the character A would be represented as "A", the character LATIN CAPITAL LETTER A WITH GRAVE would be represented as "%C3%80", and the character KATAKANA LETTER A would be represented as "%E3%82%A2".

What character set should be used for URL encoding?

HTTPリクエスト

URIのエンコーディング。つまり、HTTPリクエストのパスに使われる文字セットは UTF-8。 それ以外は必要ない。

Content-Type の charset はクライアント側でどの文字コードを使い表示するかを定めるものであって、サーバー側でどうにかするものではない認識。

CGI

CGIとのやりとりではASCIIコードを使う必要があるが、これは UTF-8 でパーセントエンコードすれば要件を満たせる。

PATH_TRANSLATED に関してはパーセントデコードする必要がある。 ただし、これもURIの仕様で UTF-8 で来ることがわかっているので、文字コードについては UTF-8 でのパーセントデコードのみ考えれば良い。

コマンドライン引数はパーセントデコードする必要がある。 4.4. The Script Command Line

RFC3875 CGI/1.1 より RFC3986 URI Generic Syntax のほうが新しい。 つまり、CGI/1.1 の仕様を決定した時点ではまだURIがUTF-8でパーセントエンコードされる仕様はなかったのかもしれない。

サーバーからはCGIスクリプトが何の文字コードで処理するかはわからない。それを考えると、URIの仕様に基づきUTF-8でデコード、エンコードされたものを渡すのが正解な気がする。

ただし、CGIスクリプトに向けてクライアント側が送信したボディに関しては Content-Typecharset にて文字コードが定められているため、CGI側はそれに基づき処理を行う。

結論

UTF-8 のパーセントエンコーディングのエンコード、デコードを作ればおk。

サーバーはリクエストの Content-Type の charset を見ない。

サーバーはCGIレスポンスの Content-Type の charset を見なくて良い。