POSTされたデータをパースするApacheモジュール
CentOS5.1 上の Apache2.2のサンプル。libapreq2 を使用。
libapreq2 のインストールには、あらかじめEPELレポジトリの追加が必要。
# rpm -ivh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-1.noarch.rpm # yum install libapreq2-devel
- mod_mypost の作成
# apxs -g -n mypost # cd mypost # make # make install
/etc/httpd/conf.d/mod_mypost.conf を以下のように作成
LoadModule mypost_module modules/mod_mypost.so <Location /mypost> SetHandler mypost </Location>
- mod_mypost.c
#include "httpd.h" #include "http_config.h" #include "http_protocol.h" #include <apreq2/apreq_param.h> #include "apr_tables.h" #include "ap_config.h" static int mypost_handler(request_rec *r) { apr_bucket_brigade *bb; int seen_eos = 0; char *body=""; if (strcmp(r->handler, "mypost")) { return DECLINED; } r->content_type = "text/html"; bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); do { apr_bucket *bucket; apr_status_t rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, APR_BLOCK_READ, HUGE_STRING_LEN); for (bucket = APR_BRIGADE_FIRST(bb); bucket != APR_BRIGADE_SENTINEL(bb); bucket = APR_BUCKET_NEXT(bucket)) { if (APR_BUCKET_IS_EOS(bucket)) { seen_eos = 1; break; } if (bucket->length != 0) { const char *data; apr_size_t len; rv = apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ); //ap_rprintf(r, "len=%d; type=%s; %s\n", len, bucket->type->name, apr_pstrmemdup(r->pool, data, len)); //ap_rprintf(r, "%s", apr_pstrmemdup(r->pool, data, len)); body = apr_pstrcat(r->pool, body, data, NULL);; } } apr_brigade_cleanup(bb); } while (!seen_eos); if (!r->header_only) ap_rprintf(r, "%s\n", body); return OK; } static void mypost_register_hooks(apr_pool_t *p) { ap_hook_handler(mypost_handler, NULL, NULL, APR_HOOK_MIDDLE); } module AP_MODULE_DECLARE_DATA mypost_module = { STANDARD20_MODULE_STUFF, NULL, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ NULL, /* table of config file commands */ mypost_register_hooks /* register hooks */ };
- apreq_body を使った改良版
#include "httpd.h" #include "http_config.h" #include "http_protocol.h" #include "apreq_module.h" #include "apreq_param.h" #include "apreq2/apreq_module_apache2.h" #include "apr_tables.h" #include "ap_config.h" static int mypost_handler(request_rec *r) { if (strcmp(r->handler, "mypost")) { return DECLINED; } r->content_type = "text/html"; apreq_handle_t *apreq; apreq = apreq_handle_apache2(r); apr_table_t *param; apreq_body(apreq, (const apr_table_t**)¶m); //to specify a value ap_rprintf(r, "%s\n", apreq_params_as_string(r->pool, param, "key", APREQ_JOIN_AS_IS)); //to enumerate values apr_array_header_t *params = apr_table_elts(param); apr_table_entry_t *paramlist = (apr_table_entry_t *)params->elts; int i; for (i=0; i<params->nelts; i++){ ap_rprintf(r, "%s==%s\n", paramlist[i].key, paramlist[i].val); } return OK; } static void mypost_register_hooks(apr_pool_t *p) { ap_hook_handler(mypost_handler, NULL, NULL, APR_HOOK_MIDDLE); } module AP_MODULE_DECLARE_DATA mypost_module = { STANDARD20_MODULE_STUFF, NULL, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ NULL, /* table of config file commands */ mypost_register_hooks /* register hooks */ };
- テスト
# curl -d 'key=val&key1=val1&key2=val2' 'http://localhost/mypost' val key==val key1==val1 key2==val2