■
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ファイルで設定されている