WWWC 1.00b79のHTTPエンジンの動作

警告: この文書は WWWC の作者によるものではなく、 赤の他人がソースコードを解読して書いたものです。
注意: 自分でソースを読んで理解できない人は この文書を鵜呑みにしてはいけません。 「動作の解説」としてリンクを張るのも誤解されるので避けましょう。 ソース読みの補助程度に考えたほうが良いでしょう。 一次情報源は常にソースコードです。

betaの なんぼであるかは使っている人にしかわかりません。 (User-Agentヘッダは"WWWC/1.00"のみ)


HEADとGETの切り替え

初めてのURLに対してはHEADを行う。
ただしプロパティ→チェック→チェックで「METAを使う」等、 request-bodyが必要だとわかっていれば最初からGET。

HEAD で Content-Length と Last-Modified、いずれも 得られなかったら、GETに切り替える。 (http.c:HeaderFunc(): ... *tpItemInfo->Option1 = '1';)
ただし切り替わったことはユーザーにはわからない。 プロパティの「GETリクエストでチェックを行う」は空欄のまま。

GETに切り替わったことは、tpItemInfo->Option1 の 第一フィールドに記録される。 Option1は "数字;;数字;;..."の形であり、 各フィールドの意味は http.c の頭の OP1_REQTYPE (0番目), OP1_NODATE (1番目) などに 割り当てられている。(http.c: #define ...)
また、この文字列は item.dat に記録されるので、 次回の起動からも同じ設定で立ち上がる。

GETに切り替わっても、200かつContent-Length:が返ってくれば HEAD動作に戻る。これもユーザーには透過。 (HeaderFunc(): ... *tpItemInfo->Option1='0'; )
Last-Modifiedだけ返ってきても戻らない。 (ソースに3行ほど書き加えれば戻るようにはなる)

GET だと Content-Length がつくが HEAD ではつかないようなURLでは、 毎回 HEAD→GETになってしまう。 サーバー(CGIでも可)を実装する側としてはその方が楽だから 実在してそうな気がする… が、真面目に対応するにも限界があるので、ここまで来たらサーバーに 泣いてもらうのもアリでしょう。

手動でHEAD動作にリセットするには、 「GETリクエストでチェックを行う」の チェックをいったん入れてから外す。

If-Modified-Since

If-Modified-Sinceには、過去にサーバーから受け取った Last-Modifiedの値しか入らない。(tpItemInfo->DLLData)

If-Modified-Sinceは、

場合にのみつく。

HEADでIf-Modified-Sinceがつくことはない。 よって 304 は返ってこないので、 Content-Length か Last-Modified の値に基づいて 更新されたかどうかの判断が行われる。 (HeaderFunc(): CmpMsg = Head_GetDate() | Head_GetSize() = {ST_DEFAULT, ST_UP})

ただし、とにかく 304 が返ってきた場合は、 めんどくさい判断は全部ヌキにして無条件で更新なしと判断される。
(HeaderFunc(): if (Status==304)... ; IMS も If-None-Match もないのに 304 を返すサーバーはないと思うが)

tpItemInfo->Option1

ビットマスクではなく、"値;;値;;..." の形式の文字列。 左端の値のindexが 0 (OP1_REQTYPE)。

OP1_REQTYPE (0, int)
0: HEADを使う (デフォルト)
1: GETを使う
2:「GETリクエストでチェックを行う」
OP1_NODATE (1, int)
1:「更新日が変っても更新とみなさない」
OP1_NOSIZE (2, int)
1:「サイズが変っても更新とみなさない」
OP1_NOTAGSIZE (3, int)
1:「HTMLタグを除いたサイズでチェックを行う」
NODATEとNOSIZEはUIレベルで排他に設定される。

CmpOption

http.c:Head_GetDate()の第2引数のCmpOptionは

(http.c:HeaderFunc()にて設定)
プロパティ→チェック→チェックのチェックボックスが ラジオボタン的な動作をするのはこれを反映している。 (OP_NODATEとOP_NOSIZEは排他)

接続の強制切断

tpHTTP->HeadCheckFlagは、 response-bodyを読み込む必要がある場合に CheckHead()内でTRUEに設定される。 常にif (tpHTTP->HeadCheckFlag == FALSE && CheckHead()==TRUE) の形で使われているので、以後CheckHead()は呼ばれなくなる。 …んーと…

論理をひっくり返して考える。

FALSEのままならヘッダだけで接続をぶち切ってもよい。 よって、tpHTTP->HeadCheckFlag==FALSE && CheckHead()==TRUEは、 「bodyは必要なく、必要なResponseヘッダは揃った」となる。 よって、HTTPRecvData(),HTTPClose()ではこのif文の後に 接続を強制切断するコードが続く。

ただし、必要なヘッダが揃っていれば、以後HEADに切り替わるように なっているので、このロジックが実際に発火するのは

の時くらいだと思われる。 (beta71〜beta77ではGET固定なのでもっと頻度は高かった、はず)

tpItemInfo->Param3

HTTPエンジンの動作モード。特に#define等はない。


参考文献


kabe@sra-tohoku.co.jp