HTDCP - HyperText Date Collecting Protocol

Ver: 0.13

Last-modified: Mon, 03 Feb 2000 04:07:30 GMT

ハイパーテキストの日付情報を集めるためのプロトコルです。 URIに対応する日付情報を管理します。 HTTP/1.1「風」のプロトコルです。 あくまでも「風」なので、互換性は適当です。 Proxyが通ればいいなぁという感じです。 POSTメソッドとHEADメソッド,VALIDATEメソッドがあります。

はじめに

なんとなくこうゆうのが欲しいなと思って作りました(おい)。 基本的にはサーバのためのプロトコルです。 このサーバは自力では更新時間を集めません (やればできるけど、面倒なのでやってないだけ)。 そのかわりPOSTで登録、HEADで読み出すことができます。 Last-modified以外のフィールドは基本的に自由に登録できます。 ただしHTTP/1.1とかで使われているものはそれに準じた扱いをします。 また、対象となっているHTMLの制作者がPass-codeを設定し、 そのダイジェストをページ中に埋め込むことによって、 情報の登録をコントロールすることも可能です (大した効果はありませんが)。 基本的にはそれだけです。 まあ、いろいろ拡張できたらいいなとは思っていますが。

そんなわけでご意見は募集中です。janus@haun.orgまで。

Syntax

だいたいHTTPと同じです。 Requestのmethodとしては以下のものがあります。 それ以外のHTTPのメソッドは予約されています。

HTTPとの違い


POST

POST SP Request-URI SP HTTP-Version CRLF
1#(entity-header CRLF)
CRLF
[message-body]

Request-URIもしくはContent-Locationフィールドの値で指定した URIのヘッダ情報をサーバに登録します。 message-bodyをヘッダ情報として登録できます。 HTDCPのヘッダ情報はmessage-bodyの情報で上書きされます。 サーバは登録に成功した場合は200 OKを、 Pass-codのチェックに失敗した場合は401 Unauthorizedを、 Last-modifiedフィールドの時刻がinvalidな場合412 Precondition Failedを 返すべきです。

message-bodyについて

POST Methodのmessage bodyはform-urlencodedされていると仮定して、 decodeを行い、fieldとvalueのペアを作ります。それらは、登録しよう としているヘッダ情報とみなしてentity-headerよりも優先して登録します (entity-headerの情報は上書きされる)。

Content-Length(オプショナル)

message-bodyがある場合は、Content-Lengthフィールドは必須です。 message-bodyがない場合は、Content-Lengthフィールドは0または不要です。

Last-modified(必須)

Last-Modifiedフィールドは必須です。 入力された時間情報が正しいかどうか検証します。 日付のフォーマットはHTTP/1.1のものと完全に同じでなければなりません。 つまりGMTで、HTTP/1.1で指定された3つのフォーマットのうちのいずれか でなければなりません。

このフィールドはproxyでも透過的に渡されると期待されます。

Content-Location(オプショナル)

登録するURIをAbsolute-URIで指定しなければなりません。 サーバはこのURIをRequest-URIより優先しなければなりません。 Absolute-URIはcase sensitiveです。

このフィールドはproxyでも透過的に渡されると期待されます。

Pass-Codeフィールド(オプショナル)

HTDCPでは、登録情報の正当性検証を行います。 正当性の検証はMD5 Digestで行います。 URI+Pass-CodeのMD5 Digestを計算し、 そのDigestがURIで指定されるHTMLの中に記述されていれば、 登録情報は正当であると判断します。 なお、HTMLの中のDigestはHTDCP-MD5:という文字列の後に 22文字のBase64エンコードで記述されているものとします。 HTML中にDigestがない場合は、登録を行います。 各URIに対応するPass-codeはHTDCPのクライアントが知っている 必要があります。HTML中にDigestが存在し、 URI+Pass-codeで生成されるDigestと一致しない場合、 サーバは情報を登録してはいけません。

Pass-codeはplain textなので、セキュリティはありません。

HEAD

POST SP Request-URI SP HTTP-Version CRLF
1#(entity-header CRLF)
CRLF
[message-body]

Request-URIもしくはContent-Locationフィールドの値で指定した URIのヘッダ情報を返します。 サーバは200 OKとともにヘッダ情報を出力します。 指定されたURIのヘッダ情報が存在しない場合は、サーバは404を 返すべきです。

[0.13での拡張] Request-URIはabsoluteURI(see RFC2396)です。

http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
Request-URI    = * | absoluteURI | abs_path
リクエストのentity-headerにHostフィールドがある場合は、 absolute-URIのhostをHostフィールドの値と置き換えます。 abs_pathの場合はRequest-URIを"http://" host abs_path とみなします(hostはHostフィールドの値)。 これはProxyを越えるために行う処置です。 `*'はサーバ自身の情報を得るために使います。

Last-modified(必須)

Last-Modified  = "Last-Modified" ":" HTTP-date

サーバはLast-modifiedフィールドを必ず返さなければなりません。 Last-modifiedフィールドの値は、URIで指定されるコンテンツの 最終更新時間であると期待されますが、基本的には登録された情報 そのままです。

Update-Date(オプショナル)

Update-Date  = "Update-Date" ":" HTTP-date

ヘッダ情報の更新時間をGMTで返します。日付フォーマットは、HTTP/1.1 に準拠する必要があります。

Host(オプショナル)(Ver. 0.13)

Host = "Host" ":" host [ ":" port ]

Request-URIで要求するサーバを指定します。HEADで実際に検索される URIはhostがこのHostに置き換えられたものになります。

VALIDATE

VALIDATE SP Request-URI SP HTTP-Version CRLF
CRLF

サーバは指定されたURIで取得できるHTML中のHTDCP-MD5を取得し、 自身が持っている情報と比較し、ダイジェストが等しくない場合は、 現在のヘッダ情報を破棄し、新しいダイジェストを記録します。 なお、サーバは前回ダイジェストを更新してから30分以上経ってから、 新しいダイジェストを取得すべきです。

HTML中にHTDCP-MD5が存在しないか、ダイジェストが等しい場合, サーバは200 OKを返します。それ以外は、401 Unauthorizedを返し、 ヘッダ情報を破棄します。

Persistent Connection

現状ではRequestメッセージの Connectionフィールドで明示的にkeep-aliveが指定されていなければ、 Responseを出力して次のRequestを待ちます(0.12から変更)。 RequestメッセージのConnectionフィールドもしくはProxy-Connectionで keep-aliveが指定されていれば、 そのまま接続を維持して次のRequestを待ちます。 RequestメッセージのConnectionフィールドにcloseが指定されてれば、 サーバはResponseメッセージのConnectionフィールドにcloseを指定して 接続を切ります。 エラーなどでもサーバから接続を切ることは原則としてありませんが、 リクエスト待ちの状態である一定時間(30秒程度が適当)入力がない 場合は、サーバは接続を切るべきです。

サンプル実装

詳しくは、サンプル実装を見て下さい(手抜き)。 PerlのDigestパッケージが必要です。 一応Keep-aliveみたいなものも実装しています。 30秒以上入力がない場合は、timeoutで接続を切ります。 あと、HTMLを取得する時はいちおうProxyにも対応しています。 forkしたりdaemon的には動作しないんで、 そのヘンは改良した方がいいかも的。 log/debug.logにログが残ります。 ま、けっこういい加減な実装なのでご勘弁。

登録手順

% telnet remote_host 9000
Trying remote_host ...
Connected to remote_host.
Escape character is '^]'.
POST http://aeneis.haun.org/janus/d/ http/1.1
Last-modified: Sun, 29 Aug 1999 09:36:24 GMT
Pass-code: xxxxxx

HTTP/1.0 200 OK
Date: Sun, 29 Aug 1999 22:25:21 GMT
Server: Nacky/0.1
Content-type: text/html

<HTML><TITLE>200 OK</TITLE></HEAD>
<BODY><H1>OK</H1></BODY></HTML>
Connection closed by foreign host.
% 

読み出し手順

% telnet remote_host 9000
Trying remote_host ...
Connected to remote_host.
Escape character is '^]'.
HEAD http://aeneis.haun.org/janus/d/ http/1.1
Connection: close

HTTP/1.0 200 OK
Date: Sun, 29 Aug 1999 22:26:07 GMT
Server: Nacky/0.1
Connection: close
Last-modified: Sun, 29 Aug 1999 09:36:24 GMT
Content-type: text/html

Connection closed by foreign host.
% 

HTDCP-MD5の計算

HTDCP-MD5を計算するページ。 URLとPass-codeを入れるとHTDCP-MD5を計算して表示します。 この結果のHTDCP-MD5の行をURLで指定したページのどこかに入れておくと、 Pass-codeを知っている人がHTDCPで更新情報を登録できます。 あくまでも紳士協定みたいなものなので、 大した効果はありませんが。 もちろん他人にPass-codeを知らせたくない人は使わない方が無難。


Reference

  1. CATS /[Spec] /[File Format]
  2. DI
  3. 朝日奈アンテナ
  4. DIXS
  5. わっちりんく(す)
  6. MICAN
  7. なつみかん