Apache 2.2.3のリクエスト処理(その2)

Apache 2.3.3のserver/request.cと、「Request Processing in Apache 2.0」http://httpd.apache.org/docs/2.2/developer/request.html
の記述に基づくメモ


全てのリクエストは、関数ap_process_request_internal(server/request.c)で処理される。
これには、サブリクエストとリダイレクトを含む。
モジュールはこの関数を通して、生成したリクエストを渡す必要がある。


フックという仕組みがある。

  • リクエスト解析段階
    • URLエスケープを元に戻す

内部リクエスト処理の最初に、リクエストのparsed_uriパスのエスケープを元に戻す。

プロキシリクエストフラグがセットされていれば、あるいはparsed_uri.pathが未設定ならこの処理は行わない。

エンコードされたスラッシュを認めるならばap_unescape_url_keep2f
エンコードされたスラッシュを認めないならばap_unescape_url

エスケープを戻す段階で不正なエスケープであることが分かれば、HTTP_NOT_FOUNDを返り値として返す

    • URLから、/../と/./を削除

ap_getparents()

(ソース中のコメント)
全てのファイルサブリクエストは大きな苦痛だ。
それらは次のいくつかのステップを(bubble through)出来ない。
許されるファイルサブリクエストは中身のないuri(empty uri)だけだ。
それでなければ、translate_nameにリクエストをkillさせる

ファイルリクエストでなければ
 ap_location_walk呼び出し
返り値が0でなければ、その値をreturn
 ap_run_translate_name呼び出し
返り値が0でなければ、その値をreturn

迂回出来ない

    • 最初のURLロケーション辿り

全てのリクエストは、ap_location_walk()の対象である。
セクションが、一貫して全てのリクエストに対して強制されることが保証される。

    • 名前の翻訳

モジュールはファイル名を決定することが出来る。
さもなくば、この段階で与えられたURIを変更する。
もしリクエストがコアにフォールバックしたら、DocumentRootを頭に付ける
もし、すべてのモジュールがこのフェーズをあきらめたら(DECLINE)、ブラウザに500が返り、「couldn't translate name」というエラーが記録される。

    • フック:map_to_strage

map_to_straceを実行する前に、リクエストのディレクトリ毎の設定を、サーバのデフォルト値に設定

ファイルまたは正確なURIが決まれば、適切なディレクトリ毎の構成が一つにまとめられる。
例えば、mod_proxyは適切なセクションを比較して、まとめる。
もしURIがローカル(非プロキシ)に過ぎないのであれば、コアはリクエストを処理し、DONEを返す。
もしどのモジュールもこのフックにOKまたはDONEで答えなければ、コアはリクエストファイル名をセクションとセクションに持っていく。
もし、リクエストファイル名が絶対パスでなく、正しいファイル名でなければ、後の処理のために注記される。

ap_run_map_to_strage()呼び出し
返り値が0でなければ返り値をreturn

    • URLロケーション辿り

すべてのリクエストは、2回目のap_location_walk呼び出しで固められる。
この呼び出しは、変換済みリクエストが、まだ修正されたセクションに従属していることを保証する
リクエストは、再び以前のロケーション辿りからすべてまたは一部の処理(処理結果?)を借りる
(これは要するにキャッシュのこと)

真のURIを持たないファイル特有のリクエストを除外する
ファイルリクエストでないならば
 ap_location_walk()呼び出し(map_to_strage設定を上書きする)
 返り値が0でなければ返り値をreturn

    • フック:header_parser

メインリクエストはクライアントのヘッダを解析する。
これは残りのリクエスト処理過程の準備をする

mainリクエストであれば
ap_run_header_parser呼び出し
 返り値が0でなければ返り値をreturn

  • セキュリティ段階

ドキュメントなし

#リクエストが、Satisfyディレクティブの指定に合わせて(ALLまたは指定なしか、ANYか)処理しているようだ。

ソースコードのコメントより)
親のリクエストまたは優先リクエストがauthn/authzを渡すならば、authn/authzをスキップする。
そして、設定を変更しない(このことにはmap_to_storage中のoptimized_walkが必要。)
もし設定が変更されれば、re-authしなければならない

mainリクエストであり、かつmainリクエストのディレクトリ毎の設定がリクエストのディレクトリ毎の設定と等しければ
 リクエストのユーザをmainリクエストのユーザにする
 リクエストのap_auth_typeをmainリクエストのap_auth_typeにする
直前のリクエストが存在し、直前のリクエストのディレクトリ毎の設定がリクエストのディレクトリ毎の設定と等しければ
 リクエストのユーザを直前のリクエストのユーザにする
 リクエストのap_auth_typeを直前のリクエストのap_auth_typeにする
上記のどれでもなければ
 リクエストのSATISFYがALLか未指定ならば
  ap_run_access_checkrを呼び出す
  返り値が0でなければ
   DECLINEDであれば
    "configureation error"をログに記録
    DECLINEDをHTTP_INTERNAL_SERVER_ERRORにする
   返り値をreturn

ap_some_auth_requiredを呼び出す
  返り値が0でなければ
   ap_run_check_user_idを呼び出して0でなければ、またはap_auth_typeが0であれば
   DECLINEDであれば
    "configureation error"をログに記録
    DECLINEDをHTTP_INTERNAL_SERVER_ERRORにする
   返り値をreturn

   ap_run_auth_checkerを呼び出して0でなければ、またはap_auth_typeが0であれば
   DECLINEDであれば
    "configureation error"をログに記録
    DECLINEDをHTTP_INTERNAL_SERVER_ERRORにする
   返り値をreturn

 リクエストのSATISFYがANYならば
  ap_run_access_checkrを呼び出す
  返り値が0でなければ
   ap_some_auth_requiredが0でなければ
    DECLINEDであれば
     "configureation error"をログに記録
     DECLINEDをHTTP_INTERNAL_SERVER_ERRORにする
    返り値をreturn

   ap_run_auth_checkerを呼び出して0でなければ、またはap_auth_typeが0であれば
   DECLINEDであれば
    "configureation error"をログに記録
    DECLINEDをHTTP_INTERNAL_SERVER_ERRORにする
   返り値をreturn
  
   ap_run_auth_checkerを呼び出して0でなければ、またはap_auth_typeが0であれば
   DECLINEDであれば
    "configureation error"をログに記録
    DECLINEDをHTTP_INTERNAL_SERVER_ERRORにする
   返り値をreturn

  • 前準備段階
    • フック:type_checker

モジュールには、対象リソースに対するURLまたはファイル名をテストし、リクエストに対しMIME情報を設定する機会がある。
mod_mime、mod_mime_magicは、ここでファイル名やコンテンツを管理者の設定(httpd.confなどでの設定)と比較して、content type, language, character set、request handlerを設定する
フィルターやリクエスト処理パラメータを設定するモジュールもある。

もしすべてのモジュールがこの段階であきらめたら(DECLINE)、ブラウザに500を返し、ログに"couldn't find types"を記録する。

ap_run_type_checkerを呼び出して0でなければ
 DECLINEDであれば
  "configureation error"をログに記録
  DECLINEDをHTTP_INTERNAL_SERVER_ERRORにする
 返り値をreturn

    • フック:fixups

多くのモジュールは、ここに来るまでに、打ち負かされている。
fixups段階では、モジュールが主導権を握ることを宣言したり、リクエストのフィールドにモジュールにとって適切な値を強制的に設定する。
常に見通しの良い機構であるわけではないが、唯一の選択肢となる場合もある。

ap_run_fixupsを呼び出して0でなければ
 DECLINEDであれば
  "configureation error"をログに記録
  DECLINEDをHTTP_INTERNAL_SERVER_ERRORにする
 返り値をreturn

  • ハンドラ段階

この段階は、ap_process_request_internal()の一部ではない。
多くのモジュールが、なんらかのコンテンツの作成の前に、1つまたは複数のサブリクエストを準備する。
コア、あるいはモジュールがap_process_request_intermal()を呼び出した後に、リクエストを作成するためにap_invoke_handler()を呼び出す。

    • フック:insert_filter

何らかの方法でコンテンツを変換するモジュールは、モジュールの値を挿入したり、既存のフィルタを上書きしらり出来る。
例えばユーザが気ままにより先進的なフィルタを設定したり
モジュールは必要に応じてフィルタの順序を変更する
返り値はない。
このフックでの処理は、常に成功するような信頼されるよいもの(でなければならない?)
(ここの意味がつかめない)

    • フック:handler

モジュールがリクエストに関与する最後の機会。
注:全ての前処理済リクエストが、handlerフックに送られるわけではない。
mod_autoindexのような、多くのモジュールが、与えられたURIに対しサブリクエストを作成するが、サブリクエストの処理には関与しない。
しかし、ユーザにサブリクエストの一覧を示す。

以下のことを覚えておくように。
フックから要求された後処理をこのモジュールへ渡さないこと
そして、要求されたときに資源を解放するリクエストプールにプールcleanupsを登録すること。
(この辺りの意味は、ソースコードで実際の処理を確認する必要あり。)

                                                    • -
  • HTTP_NOT_FOUNDが参照されている個所
    • ./server/core.c:3614:

static int default_handler(request_rec *r)
の中

リクエストのメソッドがGETまたはPOSTであれば
 リクエストのfinfo.filetypeが0であれば
  ログに"File does not exist:"を記録
  HTTP_NOT_FOUNDを返す

 リクエストのfinfo.filetypeがAPR_DIRであれば
  ログに"Attempt to serve directory:"を記録
  HTTP_NOT_FOUNDを返す

 リクエストのused_path_infoが AP_REQ_ACCEPT_PATH_INFOでなく、かつリクエストのpath_infoが存在すれば
  ログに"File does not exist:"を記録
  HTTP_NOT_FOUNDを返す
  

    • server/util.c:1552

AP_DECLARE(int) ap_unescape_url(char *url)

URLエンコードされているにも関わらず、"/"が現れたり、"\0"が現れると HTTP_NOT_FOUND

    • server/util.c:1632

AP_DECLARE(int) ap_unescape_url_keep2f(char *url)
URLエンコードされているにも関わらず、"/"が現れたり、"\0"が現れると HTTP_NOT_FOUND