ウォンツテック

そでやまのーと

ap_process_http_connectionの処理に戻ってap_read_requestをした後のwhileの中を見てみる

    while ((r = ap_read_request(c)) != NULL) {
        c->keepalive = AP_CONN_UNKNOWN;
        /* process the request if it was read 
         * without error */

        ap_update_child_status(c->sbh,
                               SERVER_BUSY_WRITE, r);
        if (r->status == HTTP_OK)
            ap_process_request(r);

ap_update_child_statusでstatusの更新をした後、HTTP_OKならばap_process_requestを呼んでいる。

  • ap_process_request /modules/http/http_request.c

まずは最初のコメントを見てみる

    /* Give quick handlers a shot at serving the 
     * request on the fast path, bypassing all of the 
     * other Apache hooks.
...
     * Use this hook with extreme care and only if you
     * know what you are doing.
     */

ap_run_quick_handlerに関する事が書いてある。他の全hook関数を回避しクライアントに速い応答をするみたいな事?が書いてある。どうやら本筋と外れているようなので放置して次へ。

    if (ap_extended_status)
        ap_time_process_request(r->connection->sbh,
                                START_PREQUEST);
    /* Not a look-up request */
    access_status = ap_run_quick_handler(r, 0);
    if (access_status == DECLINED) {
        access_status = ap_process_request_internal(r);
        if (access_status == OK) {
            access_status = ap_invoke_handler(r);
        }
    }

ap_extended_statusは/server/scoreboard.cで定義されていて初期値は0。grep-findでこれが設定されている箇所を探すと
/modules/generators/mod_status.cにset_extended_statusというAPIがありそこでap_extended_statusが変更されている。

ap_extended_statusが実際どこかで変更されて初期値0以外の値になるとap_time_process_requestが呼ばれる。これはここと最後に呼び出されそれぞれ引数としてSTART_REQUEST, STOP_REQUESTが渡される。このAPI自体は現在の時間をapr_time_now()で取得しこのAPIのスタート時間と終了時間を保存している。

次に恐らくこのAPIの中の主力関数ap_process_request_internalとその後のap_invoke_handlerを見る前にその後の処理をちょっと見てみる。

access_statusがDONEかOKの時ap_finalize_request_protocol、それ以外の時ap_dieが呼ばれる。

/* finalize_request_protocol is called at completion of
 * sending the response.  Its sole purpose is to send the
 * terminating protocol information for any wrappers 
 * around the response message body (i.e., transfer  
 * encodings).It should have been named finalize_response.
 */
AP_DECLARE(void) ap_finalize_request_protocol(request_rec *r)
{
    (void) ap_discard_request_body(r);
    /* tell the filter chain there is no more
     * content coming */
    if (!r->eos_sent) {
        end_output_stream(r);
    }
}

コメントを読むとこの関数はresponseを全て送った時に呼ばれるとある。中身は後処理。
最後は残ったパケットのflushとlogの記録のような事をやっている。

では、ap_process_request_internalを見てみる

  • ap_process_request_internal /server/request.c
/* This is the master logic for processing requests.
 * Do NOT duplicate this logic elsewhere, or the security
 * model will be broken by future API changes.  
 * Each phase must be individually optimized to pick up
 * redundant/duplicate calls by subrequests, 
 * and redirects.
 */

まずコメントを読むと、request処理の主要ロジックである!と書いてある。中心核らしき所に来た。
ap_read_requestでrequest_rec構造体に読み込んだrequestをここで処理していると思われる。

    /* Ignore embedded %2F's in path for proxy requests */
    if (!r->proxyreq && r->parsed_uri.path) {

この辺はproxy経由のなんらかの処理をしている?よくわからないので放置。

ap_getparents(r->uri);
 /* OK --- shrinking transformations... */

ap_getparentsはRFC1808に基いてURLのparse( "./"のようなpathを削除したり "../"のようなpathを正しくセットしたりしている)し、その結果をr->uriに戻している。

    /* All file subrequests are a huge pain... they 
     * cannot bubble through the next several steps.  
     * Only file subrequests are allowed an empty uri,
     * otherwise let translate_name kill the request.
     */
    if (!file_req) {
        if ((access_status = ap_location_walk(r))) {
          return access_status;
        }

        if ((access_status = ap_run_translate_name(r))) {
          return decl_die(access_status, "translate", r);
        }
    }

file_reqがNULLの場合にこのif文以下が実行される。file_reqは最初の方で定義されていて

    int file_req = (r->main && r->filename);

となっている。request_recのmainとfilenameはそれぞれ

    /** Pointer to the main request if this is 
     *  a sub-request (see http_request.h) */
    request_rec *main;
...
    /** The filename on disk corresponding to 
     *  this response */
    char *filename;

と定義されている。すなわち!file_reqが真となるのはr->mainとr->filenameのどちらかがNULLの時である。要はこのrequestがsubrequestでは無いか、このレスポンスに関連づいたfilenameが無い場合である。

ap_localtion_walkはconfigファイルで設定されているタグに関する解析がされている。