最終更新:
library_task 2010年11月28日(日) 14:40:33履歴
HTTP処理を始めるはず・・・POSTだった場合の受信がまだですがこの関数では
HTTPヘッダの値からkeepAliveを使うか、Content-Lengthヘッダがあるかなどのチェックをしています。
r->internalは、内部リダイレクトやサブリクエストであれば1が入っています。
通常のリクエスト処理では0のままなので、728行目のif文では真になります。
リクエストヘッダのConnectionヘッダを見てkeepAliveを使うか判断しているようです。
Connectionヘッダがない場合はHTTPバージョンで、HTTP1.1ならKeepAliveを使うと判断していますね。
次の747行目の処理が面白い。
ブラウザ(User-Agent)がIEで、POSTだったらKeepAliveをoffにすると。
ソース直書きでこういうことするんですね、Nginxって。
Apacheではデフォルトのhttpd.confでSSLのときブラウザがIEならKeepAliveをoffって設定がありますが
こちらは設定ファイルなのでサーバ管理者が設定変更すればIEでも許容できます。
Nginxではソースに書かれてしまっているから、問答無用でkeepAlive offですね。
757行目では、リクエストヘッダのContent-Lengthヘッダの有無を見ています。
値があればr->lingering_close = 1をセット。
これはあとでPOSTデータを取得するためでしょう。
r->phase_handler = 0 は何の意味があるのか不明です。
r->internal == 1 のときr->phase_handlerになにやら値が入っていますね。ううむ。
771行目、リクエストURLの長さが1以上であればvalid_unparsed_uri = 1がセット。
正常なリクエストである限り、1がセットされることになります。
続いて処理はngx_http_core_run_phases(r)へと続いていきます。
HTTPヘッダの値からkeepAliveを使うか、Content-Lengthヘッダがあるかなどのチェックをしています。
719 void 720 ngx_http_handler(ngx_http_request_t *r) 721 { 722 ngx_http_core_main_conf_t *cmcf; 723 724 r->connection->log->action = NULL; 725 726 r->connection->unexpected_eof = 0; 727 728 if (!r->internal) { 729 switch (r->headers_in.connection_type) { 730 case 0: 731 if (r->http_version > NGX_HTTP_VERSION_10) { 732 r->keepalive = 1; 733 } else { 734 r->keepalive = 0; 735 } 736 break; 737 738 case NGX_HTTP_CONNECTION_CLOSE: 739 r->keepalive = 0; 740 break; 741 742 case NGX_HTTP_CONNECTION_KEEP_ALIVE: 743 r->keepalive = 1; 744 break; 745 } 746 747 if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) { 748 749 /* 750 * MSIE may wait for some time if an response for 751 * a POST request was sent over a keepalive connection 752 */ 753 754 r->keepalive = 0; 755 } 756 757 if (r->headers_in.content_length_n > 0) { 758 r->lingering_close = 1; 759 760 } else { 761 r->lingering_close = 0; 762 } 763 764 r->phase_handler = 0; 765 766 } else { 767 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); 768 r->phase_handler = cmcf->phase_engine.server_rewrite_index; 769 } 770 771 if (r->unparsed_uri.len) { 772 r->valid_unparsed_uri = 1; 773 } 774 775 r->valid_location = 1; 776 #if (NGX_HTTP_GZIP) 777 r->gzip_tested = 0; 778 r->gzip_ok = 0; 779 r->gzip_vary = 0; 780 #endif 781 782 r->write_event_handler = ngx_http_core_run_phases; 783 ngx_http_core_run_phases(r); 784 }
r->internalは、内部リダイレクトやサブリクエストであれば1が入っています。
通常のリクエスト処理では0のままなので、728行目のif文では真になります。
リクエストヘッダのConnectionヘッダを見てkeepAliveを使うか判断しているようです。
Connectionヘッダがない場合はHTTPバージョンで、HTTP1.1ならKeepAliveを使うと判断していますね。
次の747行目の処理が面白い。
ブラウザ(User-Agent)がIEで、POSTだったらKeepAliveをoffにすると。
ソース直書きでこういうことするんですね、Nginxって。
Apacheではデフォルトのhttpd.confでSSLのときブラウザがIEならKeepAliveをoffって設定がありますが
こちらは設定ファイルなのでサーバ管理者が設定変更すればIEでも許容できます。
Nginxではソースに書かれてしまっているから、問答無用でkeepAlive offですね。
757行目では、リクエストヘッダのContent-Lengthヘッダの有無を見ています。
値があればr->lingering_close = 1をセット。
これはあとでPOSTデータを取得するためでしょう。
r->phase_handler = 0 は何の意味があるのか不明です。
r->internal == 1 のときr->phase_handlerになにやら値が入っていますね。ううむ。
771行目、リクエストURLの長さが1以上であればvalid_unparsed_uri = 1がセット。
正常なリクエストである限り、1がセットされることになります。
続いて処理はngx_http_core_run_phases(r)へと続いていきます。
短いですが、パッと見まったくわからない関数です。
787 void 788 ngx_http_core_run_phases(ngx_http_request_t *r) 789 { 790 ngx_int_t rc; 791 ngx_http_phase_handler_t *ph; 792 ngx_http_core_main_conf_t *cmcf; 793 794 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); 795 796 ph = cmcf->phase_engine.handlers; 797 798 while (ph[r->phase_handler].checker) { 799 800 rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]); 801 802 if (rc == NGX_OK) { 803 return; 804 } 805 } 806 }
一つ一つ見てみましょう。
ngx_http_get_module_main_confはマクロです。
#define ngx_http_get_module_main_conf(r, module) \ (r)->main_conf[module.ctx_index]これでngx_http_core_moduleに関する設定の構造体のアドレスがcmcfに返ります。
ngx_http_core_main_conf_tの型は以下のとおりです。
typedef struct { ngx_array_t servers; /* ngx_http_core_srv_conf_t */ ngx_http_phase_engine_t phase_engine; ngx_hash_t headers_in_hash; ngx_hash_t variables_hash; ngx_array_t variables; /* ngx_http_variable_t */ ngx_uint_t server_names_hash_max_size; ngx_uint_t server_names_hash_bucket_size; ngx_uint_t variables_hash_max_size; ngx_uint_t variables_hash_bucket_size; ngx_hash_keys_arrays_t *variables_keys; ngx_uint_t try_files; /* unsigned try_files:1 */ ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1]; } ngx_http_core_main_conf_t; typedef struct { ngx_http_phase_handler_t *handlers; ngx_uint_t server_rewrite_index; ngx_uint_t location_rewrite_index; } ngx_http_phase_engine_t; typedef struct ngx_http_phase_handler_s ngx_http_phase_handler_t; struct ngx_http_phase_handler_s { ngx_http_phase_handler_pt checker; ngx_http_handler_pt handler; ngx_uint_t next; }; typedef ngx_int_t (*ngx_http_phase_handler_pt)(ngx_http_request_t *r, ngx_http_phase_handler_t *ph); typedef enum { NGX_HTTP_POST_READ_PHASE = 0, NGX_HTTP_SERVER_REWRITE_PHASE, NGX_HTTP_FIND_CONFIG_PHASE, NGX_HTTP_REWRITE_PHASE, NGX_HTTP_POST_REWRITE_PHASE, NGX_HTTP_PREACCESS_PHASE, NGX_HTTP_ACCESS_PHASE, NGX_HTTP_POST_ACCESS_PHASE, NGX_HTTP_TRY_FILES_PHASE, NGX_HTTP_CONTENT_PHASE, NGX_HTTP_LOG_PHASE } ngx_http_phases;
絵にしてみた。
![](https://image01.seesaawiki.jp/n/x/nginx/487e2c5b35e6fb26.jpg)
796行目でphにhandlers構造体のポインタが入ります。
次のwhile文では、chekerに関数が登録されているか、登録されている関数に飛んでOKが返らない限り
繰り返されるwhile文です。
r->phase_handlerは今のフェーズです。enumに定義されていますが、0ならNGX_HTTP_POST_READ_PHASE
これから何か処理してフェーズが終わるとr->phase_handler ++;となるのでしょう。
今はNGX_HTTP_POST_READ_PHASEです。
ngx_http_phase_handler_pt checkerに登録されている関数に飛ぶことになります。
登録されている関数はngx_http_core_generic_phase()です。
ngx_http_core_generic_phaseは以下のとおり。
ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { ngx_int_t rc; /* * generic phase checker, * used by the post read, server rewrite, rewrite, and pre-access phases */ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "generic phase: %ui", r->phase_handler); rc = ph->handler(r); if (rc == NGX_OK) { r->phase_handler = ph->next; return NGX_AGAIN; } if (rc == NGX_DECLINED) { r->phase_handler++; return NGX_AGAIN; } if (rc == NGX_AGAIN || rc == NGX_DONE) { return NGX_OK; } /* rc == NGX_ERROR || rc == NGX_HTTP_... */ ngx_http_finalize_request(r, rc); return NGX_OK; }
ngx_http_phase_handler_t構造体のheader関数を実行。
その戻り値が NGX_OKであれば、ngx_http_phase_handler_t構造体はリンク型になっていて次の構造体へ。
NGX_DECLINEDだとr->phase_handler++;されて、フェーズが次に進む。
あれ、Apacheだとdeclinedである限り、そのフェーズ内のモジュールが呼ばれ、OKだと次へ進むなんだけど
Nginxのこのコードを見る限りNGX_DECLINEDで次のフェーズへ進むように見える。
んー、こんな感じでr->phase_handler++;されながら、様々な関数を処理していくのですね。ここがNginxのコアな部分でしょうか。
あとは各飛び先の関数でもろもろの処理をする・・・と。
このページへのコメント
VAMdnK <a href="http://sxnhwdmmxnvv.com/">sxnhwdmmxnvv</a>, [url=http://ccofquxiwikh.com/]ccofquxiwikh[/url], [link=http://xbalswvcfusr.com/]xbalswvcfusr[/link], http://vybpsimwmbwh.com/
Lv7rrI <a href="http://mnsrhevbqdgf.com/">mnsrhevbqdgf</a>, [url=http://xkysczdpjtxj.com/]xkysczdpjtxj[/url], [link=http://qbwmnqbcaixk.com/]qbwmnqbcaixk[/link], http://wnsyomsxkpoj.com/
xB2X3F <a href="http://sytwqxywehbk.com/">sytwqxywehbk</a>, [url=http://lrzmmozxdoyl.com/]lrzmmozxdoyl[/url], [link=http://tngpznyepxdo.com/]tngpznyepxdo[/link], http://jwyhbpojowkk.com/