HTTPのヘッダとHTMLのヘッダ
HTTPというプロトコルでやり取りする情報は、大きくヘッダ部分と本体部分に分かれています。
本体部分はHTMLなどのテキストであったり、各種画像などのバイナリであったりしますが、ヘッダ部分は常にテキストです。
さらに、HTMLの中身も、ヘッダ部分と本体部分に分かれています。この辺、卵の中にまた卵、みたいな感じでちょっと複雑ですが。
ヘッダ部分に関して改造したのはwf_init.cgiです。以下のような部分があるかと思います。
#---------------------------------------
# HTMLヘッダ
#---------------------------------------
sub header {
local($meta) = @_;
if ($headflag) { return; }
if ($bg) { $bg = "background=\"$bg\""; }
print "Content-type: text/html\n\n";
print <<EOM;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS">
<META HTTP-EQUIV="Content-Style-Type" content="text/css">
<STYLE type="text/css">
<!--
body,tr,td,th { font-size:$b_size; font-family:"$b_face"; }
a:hover { text-decoration:underline; color:$al; }
.num { font-family:Verdana,Helvetica,Arial; }
.obi { background-color:$backCol; color:$charCol; }
-->
</STYLE>
EOM
print "$meta\n" if ($meta);
print <<EOM;
<title>$title</title></head>
<body bgcolor="$bc" text="$te" link="$li" vlink="$vl" alink="$al" $bg>
EOM
$headflag = 1;
}
|
ここをかなり大幅に追加しました。
#---------------------------------------
# HTMLヘッダ
#---------------------------------------
sub header {
local($meta) = @_;
local($sec,$min,$hour,$day,$mon,$year,$wday)=gmtime((stat("wf_log.cgi"))[9]);
if ($headflag) { return; }
if ($bg) { $bg = "background=\"$bg\""; }
if ($mode eq "newsort" || $mode eq "rss" || $mode eq "list" || $mode eq ""){
printf("Last-Modified: %3s, %02d %3s 20%02d %02d:%02d:00 GMT\n",
$w[$wday],$day,$m[$mon],($year+1900)%100,$hour,$min);
}
print "Content-type: text/html\n\n";
print <<EOM;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="ja">
<head>
<LINK REV="MADE" HREF="mailto:toshiki\@mail.hinocatv">
<LINK REL="NEXT" HREF="http://toshiki.la.coocan.jp/">
<META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=Shift_JIS">
<META HTTP-EQUIV="Content-Style-Type" content="text/css">
<META http-equiv="Content-Script-Type" content="text/javascript">
<LINK REL="stylesheet" HREF="wforum.css" TYPE="text/css" media="all">
<LINK REL="SHORTCUT ICON" href="http://toshiki.la.coocan.jp/favicon.ico" type="image/x-icon">
EOM
print "$meta\n" if ($meta);
print <<EOM;
<title>$title</title></head>
EOM
if ($toshiki_only eq "1") {
print "<body bgcolor=\"$bc\" text=\"$te\" link=\"$li\" vlink=\"$vl\" alink=\"$al\" $bg>"
} else {
print "<body style=\"background-color:$bc; color:$te;\">"
}
$headflag=1;
}
|
この部分では、新たに以下のような機能を盛り込みました。
- ショートカットアイコン追加
- スタイルシート外部化
- ログファイルの最終更新日時情報付加
ショートカットアイコンの話は簡単ですね。HTMLヘッダのLINKタグで指定しているだけです。
スタイルシートに関しても、ちょっと大きくなったので外部ファイルにしただけで、特に変なことはしていません。
多少複雑になっているのは、全て、その他の項目に関係する部分です。
ログファイルの最終更新日時は、別になくても困らないのですが、HTMLのヘッダを見ただけで本文を読まずに新しい投稿があったかどうかを判断することが可能になるため、いわゆる更新チェッカーと呼ばれる一群のソフトのうちのいくつかでは便利になるかな、と思って搭載しました。本当は最終発言日時の方がいいのですが、それを取得するためには一旦ログを全部読まなければならず、ちょっと面倒だったため、このようになっています。
具体的には、まずログファイルの最終更新日時を取得し、それをLast-ModifiedというHTTPのヘッダ情報で出力します。
ただ、本来的には、例えばツリー一括表示のような時は、そのツリーの一番新しい発言の日時を示すべきですよね。仮に、この掲示板の全体での最新の書き込みが5分前であったとしても、現在表示されているツリーにおける最新の発言が1年前であれば、1年前の日時を表示すべきであって、5分前の日時を表示するのはおかしいでしょ。
ということで、当初は常にLast-Modifiedを出力していたのですが、現在は上記のように、新着記事系か発言リストの時のみ表示するような形になっています。
さて、コードを見てもらうとわかると思うのですが、ヘッダ表示関数を呼び出すときに任意のmetaタグを指定すれば、それをそのまま出力するようになっています。metaタグ以外を指定してもかまわないのですが、目的はあくまでもmetaタグ用、ということで。ただ、オリジナルではこれはほとんど使われておりません。わずかにwf_regi.cgiの中で、投稿完了時の自動移動のために使われているだけです。
そこで、これを使って、wforum.cgiの出力はブラウザにキャッシュするように指定してみました。
通常、掲示板のような、アクセスするたびに情報の内容が変わる可能性のある動的なコンテンツの場合、ブラウザのキャッシュにデータを保持させないような設定にしておくのが一般的です。これは、キャッシュされていると、例えば新しい書き込みがあってもそれが表示に反映されず、古い状態がそのまま表示されてしまうことになるので、きわめて当然なわけです。
そして、全くキャッシュされないと、ブラウザでどれかのスレッドの発言を見て、それから別のスレッドの発言を見るためにブラウザの戻るボタンを押したとき、当然のごとくサーバからの再読み込みが行われます。通常、これで困ることは全くないのですが、この板塀では多少困ってしまうのです。なぜなら、ブラウザからの再読み込みの要求を受け付けるこのサーバ、ちと遅い。
さらに私だけの特殊要因なんですが、掲示板メンテナンスやらレス付けやらであちこちの発言を読む必要があり、結果として「戻る」ボタンを多用する、というのもあります。
この解決策として、ブラウザでキャッシュされるよう設定してみたのです。ただ、永久にキャッシュが残るようだともちろん不都合がありますから、1時間だけキャッシュが残るような設定としました。
具体的には、キャッシュされているデータを破棄する時刻を現在の1時間後に設定したExpireというHTMLヘッダ情報を出力するように指定してheader関数を呼び出しています。こんな感じですね。
&header(sprintf("<META HTTP-EQUIV=\"Expires\" CONTENT=\"%3s, %02d %3s 20%02d %02d:%02d:00 GMT\">\n",$w[$wday],$day,$m[$mon],($year+1900)%100,$hour,$min));
|
日時データを表す変数には、あらかじめ値を代入しておきます。私の場合はwforum.cgiの先頭で1回だけ代入していますが、ひょっとするとheaderを呼び出す直前に値を取得するようにしたほうがいいかもしれません。
もしかしたら、ブラウザによっては問題があるかもしれません。
もし異常な動作を発見されましたら、ご連絡いただけると幸いです。
追記(2019.Feb.15)
このヘッダ部分について、さらに追加を行っております。
詳細は「canonical属性付加」のページをご参照ください。