何もしないOutputfilterのサンプル

http://asp.mi.hama-med.ac.jp/web/ のソースをほとんどそのままコピー。これを元に改造していく。

いつものように、

# apxs -g -n myoutputfilter
  • mod_myoutputfilter.conf
LoadModule myoutputfilter_module modules/mod_myoutputfilter.so
SetOutputFilter MYOUTPUTFILTER
  • myoutputfilter.c (本当に何もしないバージョン)
#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "apr_strings.h"
#include "apr_general.h"
#include "util_filter.h"
#include "apr_buckets.h"
#include "http_request.h"

static apr_status_t myoutputfilter_out_filter(ap_filter_t *f, apr_bucket_brigade *in_bb) {
    const request_rec* const r = f->r;

ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->status, r, ">>myoutputfilter_out_filter()");

    if (APR_BRIGADE_EMPTY(in_bb))
        return APR_SUCCESS;

    ap_remove_output_filter(f);
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->status, r, "<<myoutputfilter_out_filter()");
    return ap_pass_brigade(f->next, in_bb);
}

static void myoutputfilter_register_hooks(apr_pool_t *p)
{
    ap_register_output_filter("MYOUTPUTFILTER", myoutputfilter_out_filter, NULL, AP_FTYPE_RESOURCE);
}

module AP_MODULE_DECLARE_DATA myoutputfilter_module = {
    STANDARD20_MODULE_STUFF,
    NULL,                         /* dir config creater */
    NULL,                         /* dir merger --- default is to override */
    NULL,                         /* server config */
    NULL,                         /* merge server config */
    NULL,                         /* command table */
    myoutputfilter_register_hooks      /* register hooks */
};
  • myoutputfilter.c (in_bb を out_bb にコピーしているバージョン)
#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "apr_strings.h"
#include "apr_general.h"
#include "util_filter.h"
#include "apr_buckets.h"
#include "http_request.h"

static apr_status_t myoutputfilter_out_filter(ap_filter_t *f, apr_bucket_brigade *in_bb)
{


    const request_rec* const r = f->r;

ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->status, r, ">>myoutputfilter_out_filter()");

    if (APR_BRIGADE_EMPTY(in_bb))
        return APR_SUCCESS;

    apr_bucket_brigade* const out_bb = apr_brigade_create(r->pool, f->c->bucket_alloc);

    while (!APR_BRIGADE_EMPTY(in_bb)) {
        apr_bucket* const e = APR_BRIGADE_FIRST(in_bb);

        if (APR_BUCKET_IS_EOS(e)) {
            APR_BUCKET_REMOVE(e);
            APR_BRIGADE_INSERT_TAIL(out_bb, e);

            break;
        }

        if (APR_BUCKET_IS_FLUSH(e)) {
            apr_bucket_delete(e);

            apr_bucket* const bkt = apr_bucket_flush_create(f->c->bucket_alloc);
            APR_BRIGADE_INSERT_TAIL(out_bb, bkt);

            const apr_status_t rv = ap_pass_brigade(f->next, out_bb);
            if (rv != APR_SUCCESS)
                return rv;

            continue;
        }

        apr_size_t len;
        const char* data;
        apr_bucket_read(e, &data, &len, APR_BLOCK_READ);

        char* const buf = (char*)apr_palloc(r->pool, len);
        memcpy(buf, data, len);

        apr_bucket* const b = apr_bucket_pool_create(buf, len, r->pool, f->c->bucket_alloc);
        APR_BRIGADE_INSERT_TAIL(out_bb, b);
		
        apr_bucket_delete(e);
    }

    ap_remove_output_filter(f);
    apr_brigade_cleanup(in_bb);
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, r->status, r, "<<myoutputfilter_out_filter()");
    return ap_pass_brigade(f->next, out_bb);
}

static void myoutputfilter_register_hooks(apr_pool_t *p)
{
    ap_register_output_filter("MYOUTPUTFILTER", myoutputfilter_out_filter, NULL, AP_FTYPE_RESOURCE);
}

module AP_MODULE_DECLARE_DATA myoutputfilter_module = {
    STANDARD20_MODULE_STUFF,
    NULL,                         /* dir config creater */
    NULL,                         /* dir merger --- default is to override */
    NULL,                         /* server config */
    NULL,                         /* merge server config */
    NULL,                         /* command table */
    myoutputfilter_register_hooks      /* register hooks */
};