出力されたコンテンツをoutput filterで覗き見る
最近覗き系が多い気がしますが、解決したのでまとめておきます。
まずはソースから、デバッグ用にモジュールを1ついい加減に作ってしまいました。
static int outputfilter(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; for (backet = APR_BRIGADE_FIRST(bb); backet != APR_BRIGADE_SENTINEL(bb); backet = APR_BUCKET_NEXT(backet)) { const char *str; if (APR_BUCKET_IS_EOS(backet)) { return ap_pass_brigade(f->next, bb); } 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; } total_length += length; if (length > 0) { char* temp = (char*)apr_palloc(r->pool, total_length); if (content != NULL) memcpy(temp, content, total_length - length); memcpy(temp + total_length - length, str, length); content = temp; } } FUNC_TRACE("total_length = %d", total_length); return ap_pass_brigade(f->next, bb); }
まず1つ目のポイントがid:hkrnさんから教えていただいた、bucketのイテレートです。
APR_BRIGADE_FOREACHマクロは避けたほうがよいらしい(see http://www.schumann.cx/docs/apr-util/group__APR__Util__Bucket__Brigades.html#a80)
ので、別のマクロを利用して、forループでイテレートします。
2つ目のポイントは、1リクエストに対して、output filterが複数回呼ばれるので、覗き見するコンテンツを格納する変数がグローバルになっている点。
(マルチスレッドモードでApacheを動作させる場合は、この方法は正しくありません。tableなどに格納すべきでしょう。)
あと、id:higepon:20051121:1132566569で問題となっていた、出力が途中で切れしまう問題だが、原因が判明しました。
出力を覗くために、ap_log_errorでエラーログに出力していたのですが、こいつが長いコンテンツを途中でぶった切っていました(泣。