ヘッダの書き方

 ヘッダに書けるのは、Content-Type だけではありません。さまざまな情報を書いて、HTTP クライアントに渡すことができます。
 ところが、ヘッダは活用されているどころか、Content-Type: text/html 以外の情報は全く伝えられていないのが実情です。どうかすると、Content-Type: text/html すら書いていなかったりします。
 そこで、ここではヘッダの書き方を検討してみます。

CGI-Field

 CGI/1.1 暫定案を見ると、CGI 出力は、CGI-Field と HTTP-Field の組み合わせになっています。今まで CGI の仕様書はありませんでしたので、HTTP-Field をそのままヘッダとして流用してきました。そういう事情もあって、CGI-Field はそっくり HTTP-Field と重複しているようです。また、適当な HTTP-Field を追加できるようになってもいます。

 CGI-Field として定義されているのは、Content-Type | Location | Status | extension-header の4通りです。

Content-Type

 これは META 要素で馴染み深い Internet Media Type を示すものです。あなたが日本語文字コードの問題に悩んだことがあれば、こんな META を書いたことがあるかもしれません。

<META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=ISO-2022-JP">

 これは当初、HTTP サーバに与える情報のつもりで HTML 2.0 に入っていたのですが、実際にはサーバでなくクライアントが使うようになっています。
 予定では、HTTP 応答ヘッダに次のように入るようにしたかったのです。

Content-Type: text/html;charset=ISO-2022-JP

 CGI 出力になら、最初からこれをつけることができます。というか、CGI 出力に Content-Type 項目がないと、サーバにはそれが何なのかわからなくなります。ので、必ずつけないといけません。
 だからほとんどの CGI プログラムは、Content-Type: text/html を出力するようになってはいますが、なぜか誰も parameter をつけていないようです。HTTP サーバの方で勝手に判断してつけてもらっていいのですが、日本で使われているサーバの大半は、正しい parameter をつけてはいないようです。
 ということで上記のように、charset パラメタの追加をお勧めします。Perl で書くならば

print "Content-Type: text/html;charset=ISO-2022-JP¥n";

とすればいいわけです。

 Content-Type: text/html さえも書いていないプログラムをまれに見かけることがありますが、そういうのは論外です。

Location

 これは HTML を出力するのでなく、特定の場所へ飛ばすための項目です。JavaScript なんかにも同様の関数がありますが、それをサーバから指示できるわけです。

Location: http://www.domainname.ne.jp/anydir/anyfile.html

 この項目を出力するときでも、以降に HTML 本文を書いていけないというわけではありません。ただ実際には、何を書いてもクライアントには無視されるでしょう。また、これを HTTP-Field と併用してはいけないとされています。

Status

「『状況』って何の状況じゃい?」と疑問な方も、実物を見れば直ちに思い出すことでしょう。こういう奴です。

500 Internal Server Error

 はい、思い出しましたね?これが即ち、『状況』です。このとき、Status 項目は

Status: 500 Internal Server Error

となっているわけです。Status として使うコードは、HTTP/1.0 または HTTP/1.1 で定義されています。

 あまり知られていないようですが、Status はエラーばかりとは限りません。問題がなければ、200 OK と返していいのです。CGI 出力に Status 項目が一切見当たらないときには、サーバは 200 OK を当てはめることになっています。
 ですから、問題があるときのみ Status を指定するのでなく、問題が無いときにも Status を吐くようにした方が親切であり、わかりやすいプログラムになるでしょう。Perl で書くならば

print "Status: 200 OK¥n";

ですね。

extension-header

 CGI/1.1 仕様書草案では、CGI 仕様書にも HTTP 仕様書にも存在しないヘッダをつけてよいとされており、これを拡張ヘッダと呼びます。
 もちろん書法的には他のヘッダと同様の書き方をしなければなりませんが、他の仕様書にあるものと混乱を起こすことさえなければ、その内容は自由です。ただしヘッダ名の始めには "X-CGI-" をつけて区別するべし、とされています。

HTTP-Field

 HTTP 仕様書にある header fields のどれについても、CGI 出力のヘッダとして返すことができます。つまり、HTTP/1.0 あるいは HTTP/1.1 に定義されているヘッダのうち、好きなものを書いていいわけです。

 HTTP/1.1 について header fields を拾ってみると、ざっとこんな具合です。ちょっと比較になりませんね。

       general-header = Cache-Control            ; Section 14.9
                      | Connection               ; Section 14.10
                      | Date                     ; Section 14.18
                      | Pragma                   ; Section 14.32
                      | Trailer                  ; Section 14.40
                      | Transfer-Encoding        ; Section 14.41
                      | Upgrade                  ; Section 14.42
                      | Via                      ; Section 14.45
                      | Warning                  ; Section 14.46
                      
       request-header = Accept                   ; Section 14.1
                      | Accept-Charset           ; Section 14.2
                      | Accept-Encoding          ; Section 14.3
                      | Accept-Language          ; Section 14.4
                      | Authorization            ; Section 14.8
                      | Expect                   ; Section 14.20
                      | From                     ; Section 14.22
                      | Host                     ; Section 14.23
                      | If-Match                 ; Section 14.24
                      | If-Modified-Since        ; Section 14.25
                      | If-None-Match            ; Section 14.26
                      | If-Range                 ; Section 14.27
                      | If-Unmodified-Since      ; Section 14.28
                      | Max-Forwards             ; Section 14.31
                      | Proxy-Authorization      ; Section 14.34
                      | Range                    ; Section 14.35
                      | Referer                  ; Section 14.36
                      | TE                       ; Section 14.39
                      | User-Agent               ; Section 14.43

       response-header = Accept-Ranges           ; Section 14.5
                       | Age                     ; Section 14.6
                       | ETag                    ; Section 14.19
                       | Location                ; Section 14.30
                       | Proxy-Authenticate      ; Section 14.33
                       | Retry-After             ; Section 14.37
                       | Server                  ; Section 14.38
                       | Vary                    ; Section 14.44
                       | WWW-Authenticate        ; Section 14.47

       entity-header  = Allow                    ; Section 14.7
                      | Content-Encoding         ; Section 14.11
                      | Content-Language         ; Section 14.12
                      | Content-Length           ; Section 14.13
                      | Content-Location         ; Section 14.14
                      | Content-MD5              ; Section 14.15
                      | Content-Range            ; Section 14.16
                      | Content-Type             ; Section 14.17
                      | Expires                  ; Section 14.21
                      | Last-Modified            ; Section 14.29
                      | extension-header

       extension-header = message-header

 Cache-Control を始めとして、なかなか興味深いものがたくさん並んでいるのですが、とても全部は紹介し切れません。HTTP/1.1 を参照してください。

ヘッダと本文との区切り

 さて、ヘッダはどこかで本文と区別しなければなりません。区切り子には空行を用います。つまり、ヘッダから1行空けて始まる部分から以降は、HTTP 通信文本文と看做されます。

Status: 200 OK
Content-Type: text/html;charset=ISO-2022-JP
Content-Language: ja

<-- ここから本文 -->

という具合に書くわけですね。Perl で書くなら

print "Content-Type: text/html;charset=ISO-2022-JP¥n";
print "Status: 200 OK¥n";
print "¥n";
print "<!DOCTYPE HTML PUBLIC ¥"-//W3C//DTD HTML 4.0//EN¥">¥n";
print "<HTML>¥n";
...

 あるいはヒアドキュメントを用いて

print <<EOF;
Content-Type: text/html;charset=ISO-2022-JP
Status: 200 OK

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD>
<TITLE>出力結果</TITLE>
</HEAD>
<BODY>
<H1>出力結果</H1>
# 以下HTML本文を記述
</BODY>
</HTML>
EOF

という書き方になるでしょう。多くの CGI プログラムでは、この空行を直前の行にくっつけて

print "Content-Type: text/html¥n¥n";
print "<HTML>¥n";
...

という書き方をしていますが、プログラムが見にくくなるので、あまりよい書き方であるとは思えません。

Copyright(C): 2000, 魔術幻燈
poetlabo@cap.bekkoame.ne.jp