しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

IIS の HTTP 圧縮モジュールは拡張可能らしいので bzip2 で圧縮するモジュールを作ってみた

IIS に組み込まれている HTTP 圧縮を行うモジュールはデフォルトで gzip / deflate を使うようになっています。このあたりの設定は applicationHost.config に書いてあるのですぐに分かります。

scheme で dll を指定している点が気になったので、とりあえず gzip.dll を Dependency Walker で開いてエクスポートされている関数を調べました。

すると 6 つの関数をエクスポートしているのが分かったので、関数名で適当に検索してみると MSDN のリファレンスページが見つかりました。

読んだ感じでは、この関数をエクスポートしていれば圧縮エンジンを差し替え可能なようです。

Microsoft previous versions of technical documentation | Microsoft Learn

IIS は結構柔軟に拡張できるようになっていました。これなら Google が独自に実装している SDCH に対応出来るかも思いましたが、難易度が高そうだったので bzip2 で圧縮するモジュールを作りました。

ソースコード一式は既に GitHub に上げています。

ビルドすると bzip2.dll が生成されるので、gzip.dll の代わりに設定するだけです。

これで IIS を再起動すると Accept-Encoding: bzip2 の時に圧縮されて返されます。

ただし、現状では bzip2 に対応しているブラウザは存在しないので、一先ず curl を使って直接ダウンロードを試してみます。-H オプションでヘッダーを指定するだけで確認できます。

見た感じ、圧縮されているように見えますが正しいのかわかりません。なので、bz2 拡張子のファイルとして保存して、対応したアーカイバーで展開してみました。

問題なく展開が出来て、ファイルが壊れているといったこともありませんでした。

苦労した点について

IIS HTTP 圧縮モジュールで一番重要な Compress 関数の実装でとても悩みました。具体的にはリファレンスに書いてある通りに S_OK を返していると、IIS のワーカープロセスが一瞬で暴走してしまいました。

いろいろ調べたところ、圧縮するものが無くなったタイミングで input_buffer_size が 0 で呼び出されるので、その時に S_FALSE を返すことで処理の完了を伝えることが出来ました。

return input_buffer_size == 0 ? S_FALSE : S_OK;

しょうもないミスとしては、x64 で動作している IIS なのに x86 でビルドした dll を指定していて起動しないとかありました。IIS に関しては全て x64 として作るのが良いと思いました。