Saturday, February 26, 2011

apache libapreq のソース読み


apacheモジュールでGETやPOSTのパラメータを処理するときは、libapreq2 を使って、 以下のように書けばよいが、
    apreq_handle_t *hl = apreq_handle_cgi(r->pool);
    apr_table_t *params = apreq_params(hl, pool);
どこでquery string をパースしてるのかを調べてみた。
  1. apreq_handle_t の初期化
    library/module_cgi.c
        655 APREQ_DECLARE(apreq_handle_t *)apreq_handle_cgi(apr_pool_t *pool)
        671     req->handle.module        = &cgi_module;
        677     req->args_status =
        678         req->jar_status =
        679             req->body_status = APR_EINIT;
    
    cgi_module がどこにも定義されていないと思ったら以下のMACROが
        653 static APREQ_MODULE(cgi, 20050425);
    
    以下に展開される
    static const apreq_module_t cgi_module = { "cgi", 20050425, cgi_jar, cgi_args, cgi_body, cgi_jar_get, cgi_args_get, cgi_body_get, cgi_parser_get, cgi_parser_set, cgi_hook_add, cgi_brigade_limit_get, cgi_brigade_limit_set, cgi_read_limit_get, cgi_read_limit_set, cgi_temp_dir_get, cgi_temp_dir_set, };
    
  2. apreq_params の中身
    library/module.c
         32 APREQ_DECLARE(apr_table_t *)apreq_params(apreq_handle_t *req, apr_pool_t *p)
         33 {
         34     const apr_table_t *args, *body;
         35     apreq_args(req, &args);
         36     apreq_body(req, &body);
         37
         38     if (args != NULL)
         39         if (body != NULL)
         40             return apr_table_overlay(p, args, body);
         41         else
         42             return apr_table_copy(p, args);
         43     else
         44         if (body != NULL)
         45             return apr_table_copy(p, body);
         46         else
         47             return NULL;
         48
         49 }
    
    apreq_args が cgi_argsを呼んでGETパラメータ, apreq_body が cgi_body, cgi_read を呼んでPOSTパラメータに対応する
  3. cgi_args でGETパラメータ初期化
    ./library/param.c
        140 APREQ_DECLARE(apr_status_t) apreq_parse_query_string(apr_pool_t *pool,
        141                                                      apr_table_t *t,
        142                                                      const char *qs)
    
  4. cgi_body cgi_read でPOSTパラメータ初期化 mod_apreq を使う場合や、apreq_initialize() を呼んだときに、 以下のパース用関数が、content-type にあわせて用意されている。
    library/parser.c
        114     default_parsers = apr_hash_make(default_parser_pool);
        115
        116     apreq_register_parser("application/x-www-form-urlencoded",
        117                           apreq_parse_urlencoded);
        118     apreq_register_parser("multipart/form-data", apreq_parse_multipart);
        119     apreq_register_parser("multipart/related", apreq_parse_multipart);
    
    URL エンコードされた POST に対しては以下の関数で処理される。
    ./library/parser_urlencoded.c
        158 APREQ_DECLARE_PARSER(apreq_parse_urlencoded)