output_filterで出力を覗き見してみようよ
いろいろなモジュールのコードを読んで切り貼りして output_filter を書いてみました。
まだ動作が微妙で、コンテンツが途中で切れたりします。
このあたりは、日本語の資料が少ないのは当然、英語の資料も少ないです(;´Д`)。
まずは、output_filter を登録
// registers_hooksで ap_register_output_filter("mod_my", my_output_filter, NULL, AP_FTYPE_RESOURCE); // 最後の引数これでよいんだろうか?
コンテントハンドラなどで add する。registerだけで動くかと思いきやこれを書かないと呼ばれない。
ap_add_output_filter("mod_my", NULL, r, r->connection);
output_filter は出力の度に呼ばれるっぽい。
つまり、Apacheはコンテンツを一度に出力するのではないってことだ。
apr_bucket_read の最後の引数は、APR_BLOCK_READ/APR_NONBLOCK_READは、READの際にスレッドがブロックされるかという意味だと思うんだが。
どちらが主流なのか分からないのが痛い。
static char* content = ""; // このあたりは static apr_size_t total_length = 0; // 後でどうにかしよう static int my_output_filter(ap_filter_t* f, apr_bucket_brigade* bb) { request_rec* r = f->r; apr_bucket* backet; apr_size_t length = 0; apr_status_t read_status; if (r->main) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } FUNC_TRACE("~~~~~~~~~~~~~~ output_filter for %s ~~~~~~~~~~~~~", r->unparsed_uri); APR_BRIGADE_FOREACH (backet, bb) { const char *str; if (APR_BUCKET_IS_EOS(backet)) { return ap_pass_brigade(f->next, bb); } if (APR_BUCKET_IS_FLUSH(backet)) { continue; } // read_status = apr_bucket_read(backet, &str, &length, APR_NONBLOCK_READ); read_status = apr_bucket_read(backet, &str, &length, APR_BLOCK_READ); if (read_status != APR_SUCCESS) { ERROR("apr_bucket_read error [\d]", read_status); return read_status; } FUNC_TRACE("[%s]", str); FUNC_TRACE("length = %d", length); content = apr_pstrcat(r->pool, content, str, NULL);// 怪しい total_length += length; } FUNC_TRACE("total_length = %d", total_length); return ap_pass_brigade(f->next, bb); }
同じURIに対してでも、コンテンツが取れるときと、中途半端で切れるときがある。
というのが課題。
Apache 2.x系に対応した、Apacheモジュールの本誰か書いてくれないかなぁ。
Apacheモジュール プログラミングガイド (Advanced Server‐side programmingシリーズ)
- 作者: 小山浩之
- 出版社/メーカー: 技術評論社
- 発売日: 2003/08/01
- メディア: 単行本
- 購入: 1人 クリック: 81回
- この商品を含むブログ (26件) を見る