ICAP(Internet Content Adaptation Protocol)メモ (ちょい訳?)
目的は、今までProxy等に直接実装されていたHTTPメッセージ書き換え機能の外部化。
仕様 RFC3507: http://tools.ietf.org/html/rfc3507
セマンティクス
ICAPサーバは、Proxyの裏でメッセージ書き換え機能を担当する。RFC3507は"ICAP/1.0"。今のところこのバージョンしかない。
ICAPサーバと繋がっているHTTP Proxyを"HTTP surrogate"と呼ぶ。基本的に、HTTP surrogateがHTTPメッセージを横取りして、ICAPサーバに送りつけて変換させ、返ってきた結果を使う。コンテンツフィルタリングや、ウィルスチェックや、コンテンツ変換や、画像圧縮や、翻訳等に使える。
ICAPサーバが提供するメソッドはREQMOD(HTTPリクエストの書き換え), RESPMOD(HTTPレスポンスの書き換え), OPTIONSの3種類である。これらはクライアントが呼び分ける。最初にOPTIONSメソッドを呼んで、該当ICAPサーバが提供する機能を確認する。
REQMODでは、HTTP surrogateは受け取ったユーザのHTTPリクエストを、すぐにICAPサーバに送りつけて書き換える。
RESPMODでは、HTTP surrogateはいったんユーザのHTTPリクエストをHTTPサーバへ送り、その結果をICAPサーバに送って書き換える。
ICAPサーバは、リクエスト書き換え要求に対し、リクエストを書き換える代わりに、いきなりレスポンスを送りつけても良い。フィルタリング等で有効。
ICAPは、TCP/IP上のrequest/responseプロトコルとして設計されている (4, 8.1)
- HTTP上には乗っていない。マッチングさせるのが面倒らしい。
- メッセージの形態はHTTPスタイル (4.1)
- keep-aliveのためのルールはHTTP/1.1と同じ(4.1)
- 書き換えたいHTTPメッセージがICAPメッセージに包含されているので(Encapsulated)、必要な書き換えを施して、もしくは必要なHTTP Responseを生成して、ICAP Response Messageとして戻す。
ICAP_URI (4.2)
icap://[userinfo@]host[:port]/absolute_path[?query]
ICAPヘッダ (4.3)
ユーザ定義ヘッダは"X-"で開始すること。フィールド名はcase-insensitive。
Request/Responseで共通のヘッダ (4.3.1)
HTTPと共通なものは以下。
- Cache-Control
- Connection
- Date
- Expires
- Pragma
- Trailer
- Upgrade
Transfer-Encodingは使えない。
ICAP specificなのは以下。
- Encapsulated
Requestヘッダ (4.3.2)
ICAPのメソッドは次の三種類。ユーザ定義で増やしても良い。
- REQMOD (Optional)
- RESPMOD (Optional)
- OPTIONS (MUST)
リクエストラインの例:
RESPMOD icap://icap.example.net/translate?mode=french ICAP/1.0
Request-specificヘッダのうち、HTTPから継承されたものは以下。
- Authorization
- Allow
- From
- Host
- Referer
- User-Agent
ICAP specificなものは以下。
Responseヘッダ (4.3.3)
ステータスラインの例:
ICAP/1.0 200 OK
ステータスコードは基本的にHTTPに従う。HTTPと意味が異なるのは以下の2種である。
- 100 - Continue after ICAP Preview.
- 204 - No modifications needed.
その他のエラーコード:
- 400 - Bad request.
- 404 - ICAP Service not found.
- 405 - Method not allowed for service. (REQMODしか対応していないサービスにRESPMODを送った)
- 408 - Request timeout.
- 500 - Server error.
- 501 - Method not implemented.
- 502 - Bad Gateway. ICAP proxyとして動いていて、さらに裏にあるサーバがerrorを返した。
- 503 - Service overloaded.
- 505 - ICAP version not supported by server.
HTTPと共通のResponse specificヘッダは以下。
- Server
ICAP-specificなのは以下。
- ISTag
HTTPメッセージのencapsulation (4.4, 4.4.1, 4.4.2)
この辺りからオリジナリティ。同時にメモモードに移行。
ICAPメッセージはHTTP requestもしくはHTTP request/responseのメッセージを包含している(カプセル化)。カプセル化されたHTTPメッセージを"encapsulated"、それを包み込んでいるICAPメッセージ部分を"encapsulating"と呼ぶ。
なお、ICAPではデフォルトでHTTPの"chunked" transfer-codingを用いる。メッセージのプレビューを実現するためである。ただし、"Transfer-Encoding"ヘッダは存在しないことに注意。
まず、すべてのICAPメッセージはEncapsulatedヘッダを持たなければならない(MUST)。
Encapsulated: req-hdr=0, res-hdr=45, res-body=100
req-hdrとかは見ればわかる意味(encapsulated entity)。数字はICAPボディ開始点からのバイトオフセット(10進数)。
encapsulated entityには以下がある。
- reqhdr
- reshdr
- reqbody
- resbody
- optbody
encapsulated entityの宣言順は、実際にそれがバイトストリーム上に現れる順番と一致しなければならない(MUST)。つまり、offsetの数字は単調増加で無ければならない(MUST)。
どのメソッドのRequest/Responseであるかにより、宣言可能なencapsulated entityが決まってくる。
- REQMOD requestのとき: [req-hdr] req-body
- REQMOD responseのとき: {[req-hdr] req-body} | {[res-hdr] res-body}
- RESPMOD requestのとき: [req-hdr] [res-hdr] res-body
- RESPMOD responseのとき: [res-hdr] res-body
- OPTIONS responseのとき: opt-body
一つのICAPメッセージにbodyは一つのみ。bodyが存在しない場合は"null-body"を宣言する。例えば
Encapsulated: req-hdr=0, null-body=412
RESPMODメソッドではHTTP Requestのボディは取れないことに注意。
ICAPメッセージに含まれるHTTPメッセージは、通常のHTTPと同じく、リクエストライン/ステータスラインで始まり(MUST)、ヘッダが並び、空行が入り(MUST)、必要があればボディが続く形態をとる。従って、空行でもreq-hdrとreq-body等を分離することは可能になる。
- ICAPメッセージは、End-to-End HTTPヘッダをencapsulateすべきである(SHOULD)。
- ICAPメッセージは、Hop-by-Hop HTTPヘッダをencapsulateすべきでない(MUST NOT)。
ただし、"Proxy-Authenticate"ヘッダと"Proxy-Authorization"ヘッダは、Hop-by-Hopではあるが、ICAPヘッダを使って転送されなければならない(MUST)。Encapsulated body内ではないことに注意。
HTTP surrogateがproxyとして付加したEncapsulated messageに含まれる"Via"ヘッダは、ICAPサーバが書き換えるべきである(SHOUlD)。付加するViaヘッダはプロトコルとして"ICAP/1.0"を指定しなければならない(MUST)。
REQMODメソッドでResponseを直接返す場合などには不要。また、"ICAP/1.0"を指定しろと書いてある割に、その後のサンプルでは"1.0"としか書いていない。ただし、HTTP仕様的には"protocol-name '/' version"なので、やはり"ICAP/1.0"が望ましいだろう。
メッセージプレビュー (4.5)
ICAP clientは、ICAPリクエストをサーバに送る際、「プレビュー」を含めることができる。ICAPサーバはこれにより、書き換えが必要であるかどうかを早期に判断してopt-outすることが可能である。
OPTIONSメソッドにより、ICAPサーバは何byteが必要かを指定すべきである(SHOULD)。クライアントは少なくとも4096バイトのプレビューを提供する能力を持つべきである(SHOULD be able to)。クライアントは、プレビューを希望するICAPサーバに対しプレビューを提供すべきであり(SHOULD)、サーバが提示した希望サイズより大きなプレビューを渡すべきでない(SHOULD NOT)。
ICAPクライアントは、プレビューを行う際には、プレビューの長さを示す"Preview"ヘッダを含めなければならない(MUST)。Previewヘッダの示す値は0でも良い。
ICAPクライアントは、ICAPヘッダを送った後、Previewヘッダで示した分だけ(か、それより少ない)のボディを送り、そこで送信を中断して、ICAPサーバのレスポンスを待つ。プレビューとそれ以降のデータは別のchunkになるため、ICAPサーバはバイトストリームから明確にプレビューの終わりを知ることができる。chunkの終わりには、"0\r\n\r\n"ターミネータが付く(RFC中のメッセージサンプルは間違っている)。
HTTPの100 Continueに似ているが、HTTPの場合にはヘッダ送信終了時に待つのに対し、ICAPではボディを途中まで送ってから待つことができる。
プレビューに対するICAPサーバのレスポンスは、以下の3つの内どれかでなければならない(MUST)。
- 204 No Content. ICAPサーバはリクエストに対して何もする気がない。
- REQMOD / RESPMOD レスポンス。ICAPサーバは完全なレスポンスを直接返す。
- 100 Continue. ICAPサーバはリクエストの残りが必要。ICAPクライアントは残りのデータをプレビューの次のchunkから送らなければならない(MUST)。メッセージの全てがプレビューchunkに入ってしまっている場合は、ICAPサーバは100 Continueを送ってはならない(MUST NOT)。
ICAPはHTTPサーバから何byte受け取れるか不明なので、プレビュー内では、実際のメッセージの終わりを示す方法が必要である。このために、HTTP/1.1に基づいて、"ieof" chunk extensionを使う。ICAPクライアントは、プレビューの最後のchunkのターミネータとして、これを用いる。プレビュー以外では不要であることに注意。
\r\n 0; ieof\r\n\r\n
1024byteのPreviewを宣言した状態で、HTTPサーバが1024byteを2つのchunkに分けて送った場合、ICAPリクエストのencapsulated bodyは以下になる。
200\r\n <512 bytes of data>\r\n 200\r\n <512 bytes of data>\r\n 0; ieof\r\n\r\n
1024byteのPreviewを宣言した状態で、HTTPサーバが1025bytes送ってきた場合。この場合、プレビューは終了しているので、最後のchunkは単純に"0\r\n\r\n"でよい。
200\r\n <512 bytes of data>\r\n 200\r\n <512 bytes of data>\r\n 0\r\n\r\n <サーバは100 Continueメッセージを応答> 1\r\n <1 byte of data>\r\n 0\r\n\r\n
"204 No Content"
ICAPクライアントは、HTTPメッセージ全体を保存しておき、ICAPサーバの"No Content"に対応しても良い(MAY)。その場合、ICAPリクエストヘッダに"Allow: 204"を指定すること。
ICAPサーバは、"Allow: 204"を含まないリクエストを受け取った場合、204を返してはならない(MUST NOT)。ただし、プレビューはこの限りでない。
ISTag ("ICAP ServiceTag")
ICAPサーバは、全てのICAPレスポンスに対して"ISTag"ヘッダを含めなければならない(MUST)。ISTagは、そのICAP URIが示すサービスの同一性を示す一種の"cookie"である。ISTagは、null文字を含まない英数字で構成された32バイトまでの文字列である。例えばソフトウェア名とバージョンなどが考えられる。ISTagが変わらないうちは、前回の変更内容は今でも最新であると判断できる。
例えば、ウィルスチェックサービスであれば、データベースのupdateに伴いISTagを変更することで、HTTP surrogate中のキャッシュが無効であることを示すことができる。
OPTIONS
OPTIONSレスポンスが返せるヘッダは以下のとおり。
- Methods (MUST) - MethodsにOPTIONSを含めてはならない(MUST NOT)
- Service (Optional) - サービス名
- ISTag (MUST)
- Encapsulated (MUST)
- Opt-body-type - opt-bodyが存在する場合は含めなければならない(MUST)。
- Max-Conections (Opional)
- Options-TTL (Optional)
- Date (Optional) - RFC1123
- Service-ID (Optional)
- Allow (Optional) : このRFCでは"204"だけが定義されている。
- Preview (Optional) : プレビュー時の送信バイト数。
- Transfer-Preview(Optional) : プレビューを送るべきファイル種別のファイル拡張子(!!!)のリスト。
- Transfer-Ignore (Optional) : ICAPサーバに送るべきでないファイル種別のファイル拡張子のリスト。
- Transfer-Complete (Optional) : プレビューなしで全体を送るべきファイル種別のファイル拡張子のリスト。
Transfer-*ヘッダのどれか一つは"*"を含まなければならないことに注意。
もし、Transfer-*が一つも送られなかった場合、プレビューなしで全てのメッセージがICAPサーバに送られる。
実際のサンプル
難しくないので、RFCをそのまま見ること。
この辺も参考http://www.symantec.com/region/jp/techsupp/enterprise/savse/se43/savse43_dg.pdf