最終更新: library_task 2010年11月13日(土) 09:55:56履歴
名前からして明らかですが、HTTPのリクエストラインを処理する関数でしょう。
このあたりはわかりやすいつくりだと思います。
まだリクエストラインを受信していないけど、この場合エラー画面はどうなるんだろう。
ngx_http_close_request()を見ればよいのですが、いったん飛ばします。
rev->timedout=1が入るのもどこか・・・おそらくepoll_waitあたりだと思うけどこれも後回し。
処理長っ。
for文のループですね。
for文を抜ける条件は・・・いっぱいある。
コードを細かく前にまず、予想。
リクエストラインを読む関数なので、for文のループを抜けるのはリクエストラインを抜けるまで。
1行目が改行の場合を考えてfor文ループか、この処理でHTTPヘッダ部をすべて観てしまうかのどちらか。
まずは必ず最初にngx_http_read_request_header()を通ります。
ここではrecv()をしており、クライアントからの受信データが入ります。
関数の概要は以下のとおり。
関数:ngx_http_read_request_header
戻り値:受信したサイズ
受信したデータはr->header_in->posのアドレスからr->header_in->lastまでに入っています。
よって、r->header_inでは受信したデータが入りました。受信したデータサイズはnです。
そして次にngx_http_parse_request_line()が呼ばれます。
関数:ngx_http_parse_request_line
戻り値: NGX_HTTP_PARSE_INVALID_REQUEST ⇒ フォーマットエラー
NGX_AGAIN ⇒ フォーマットは合っていてLFで終わらなかった場合
NGX_OK ⇒ フォーマットがあってLFで終わった場合
処理内容:
リクエストラインの解析。すなわち[HTTPメソッド] [URI] [HTTPバージョン]をパースする。
HTTPメソッドはr->method、URIはr->uri_start,r->uri_end、HTTPバージョンはr->http_major,r->http_minorに入る。
その他、http://形式で入っていた場合スキーマやポート番号をr->port_startなどに入る。
ということで、ngx_http_parse_request_lineはリクエストラインだけを処理します。
ここでNGX_OKだとngx_http_process_request_headers()を経て、returnですね。
for文のループは、LFがない場合ってことですね。
すごい長いURLを指定した場合なんかがNGX_AGAINのままですね。
長いURLの場合は、ngx_http_alloc_large_header_bufferのようです。
せっかくなので見てみました。
設定項目large_client_header_buffersで設定した値と比較している。
large_client_header_buffersでは「num」と「バッファーサイズ」を設定する。
バッファーサイズは受信したヘッダデータが超えていないかチェックし、超えていた場合はNGX_DECLINEDで返る。
一方の「num」がわからない。
こっちはhttp_connection構造体のnbusyという値と比較しているがこれは何の数値だろう??
それが何だかわからず。
さて、正常処理だとここでは最終的に以下のようになりますん。
HTTPヘッダ部の受信する関数でしょう。
このあたりはわかりやすいつくりだと思います。
676 static void 677 ngx_http_process_request_line(ngx_event_t *rev) 678 { 679 u_char *host; 680 ssize_t n; 681 ngx_int_t rc, rv; 682 ngx_connection_t *c; 683 ngx_http_request_t *r; 684 ngx_http_core_srv_conf_t *cscf; 685 686 c = rev->data; 687 r = c->data; 688 689 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, 690 "http process request line"); 691 692 if (rev->timedout) { 693 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); 694 c->timedout = 1; 695 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); 696 return; 697 }rev->timedoutが真であれば、タイムアウトエラーで終了となってます。
まだリクエストラインを受信していないけど、この場合エラー画面はどうなるんだろう。
ngx_http_close_request()を見ればよいのですが、いったん飛ばします。
rev->timedout=1が入るのもどこか・・・おそらくepoll_waitあたりだと思うけどこれも後回し。
698 699 rc = NGX_AGAIN; 700 701 for ( ;; ) { 702 703 if (rc == NGX_AGAIN) { 704 n = ngx_http_read_request_header(r); 705 706 if (n == NGX_AGAIN || n == NGX_ERROR) { 707 return; 708 } 709 } 710 711 rc = ngx_http_parse_request_line(r, r->header_in); 712 713 if (rc == NGX_OK) { 714 715 /* the request line has been parsed successfully */ 716 717 r->request_line.len = r->request_end - r->request_start; 718 r->request_line.data = r->request_start; 719 720 721 if (r->args_start) { 722 r->uri.len = r->args_start - 1 - r->uri_start; 723 } else { 724 r->uri.len = r->uri_end - r->uri_start; 725 } 726 727 728 if (r->complex_uri || r->quoted_uri) { 729 730 r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1); 731 if (r->uri.data == NULL) { 732 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 733 return; 734 } 735 736 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); 737 738 rc = ngx_http_parse_complex_uri(r, cscf->merge_slashes); 739 740 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) { 741 ngx_log_error(NGX_LOG_INFO, c->log, 0, 742 "client sent invalid request"); 743 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); 744 return; 745 } 746 747 } else { 748 r->uri.data = r->uri_start; 749 } 750 751 752 r->unparsed_uri.len = r->uri_end - r->uri_start; 753 r->unparsed_uri.data = r->uri_start; 754 755 756 r->method_name.len = r->method_end - r->request_start + 1; 757 r->method_name.data = r->request_line.data; 758 759 760 if (r->http_protocol.data) { 761 r->http_protocol.len = r->request_end - r->http_protocol.data; 762 } 763 764 765 if (r->uri_ext) { 766 if (r->args_start) { 767 r->exten.len = r->args_start - 1 - r->uri_ext; 768 } else { 769 r->exten.len = r->uri_end - r->uri_ext; 770 } 771 772 r->exten.data = r->uri_ext; 773 } 774 775 776 if (r->args_start && r->uri_end > r->args_start) { 777 r->args.len = r->uri_end - r->args_start; 778 r->args.data = r->args_start; 779 } 780 781 #if (NGX_WIN32) 782 { 783 u_char *p; 784 785 p = r->uri.data + r->uri.len - 1; 786 787 if (*p == '.' || *p == ' ') { 788 789 while (--p > r->uri.data && (*p == '.' || *p == ' ')) { 790 /* void */ 791 } 792 793 r->uri.len = p + 1 - r->uri.data; 794 795 ngx_http_set_exten(r); 796 } 797 } 798 #endif 799 800 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 801 "http request line: \"%V\"", &r->request_line); 802 803 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 804 "http uri: \"%V\"", &r->uri); 805 806 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 807 "http args: \"%V\"", &r->args); 808 809 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 810 "http exten: \"%V\"", &r->exten); 811 812 if (r->host_start && r->host_end) { 813 814 host = r->host_start; 815 n = ngx_http_validate_host(r, &host, 816 r->host_end - r->host_start, 0); 817 818 if (n == 0) { 819 ngx_log_error(NGX_LOG_INFO, c->log, 0, 820 "client sent invalid host in request line"); 821 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); 822 return; 823 } 824 825 if (n < 0) { 826 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 827 return; 828 } 829 830 r->headers_in.server.len = n; 831 r->headers_in.server.data = host; 832 } 833 834 if (r->http_version < NGX_HTTP_VERSION_10) { 835 836 if (ngx_http_find_virtual_server(r, r->headers_in.server.data, 837 r->headers_in.server.len) 838 == NGX_ERROR) 839 { 840 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 841 return; 842 } 843 844 ngx_http_process_request(r); 845 return; 846 } 847 848 849 if (ngx_list_init(&r->headers_in.headers, r->pool, 20, 850 sizeof(ngx_table_elt_t)) 851 != NGX_OK) 852 { 853 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 854 return; 855 } 856 857 858 if (ngx_array_init(&r->headers_in.cookies, r->pool, 2, 859 sizeof(ngx_table_elt_t *)) 860 != NGX_OK) 861 { 862 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 863 return; 864 } 865 866 c->log->action = "reading client request headers"; 867 868 rev->handler = ngx_http_process_request_headers; 869 ngx_http_process_request_headers(rev); 870 871 return; 872 } 873 874 if (rc != NGX_AGAIN) { 875 876 /* there was error while a request line parsing */ 877 878 ngx_log_error(NGX_LOG_INFO, c->log, 0, 879 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]); 880 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); 881 return; 882 } 883 884 /* NGX_AGAIN: a request line parsing is still incomplete */ 885 886 if (r->header_in->pos == r->header_in->end) { 887 888 rv = ngx_http_alloc_large_header_buffer(r, 1); 889 890 if (rv == NGX_ERROR) { 891 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 892 return; 893 } 894 895 if (rv == NGX_DECLINED) { 896 r->request_line.len = r->header_in->end - r->request_start; 897 r->request_line.data = r->request_start; 898 899 ngx_log_error(NGX_LOG_INFO, c->log, 0, 900 "client sent too long URI"); 901 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE); 902 return; 903 } 904 } 905 } 906 }
処理長っ。
for文のループですね。
for文を抜ける条件は・・・いっぱいある。
コードを細かく前にまず、予想。
リクエストラインを読む関数なので、for文のループを抜けるのはリクエストラインを抜けるまで。
1行目が改行の場合を考えてfor文ループか、この処理でHTTPヘッダ部をすべて観てしまうかのどちらか。
まずは必ず最初にngx_http_read_request_header()を通ります。
ここではrecv()をしており、クライアントからの受信データが入ります。
関数の概要は以下のとおり。
関数:ngx_http_read_request_header
戻り値:受信したサイズ
受信したデータはr->header_in->posのアドレスからr->header_in->lastまでに入っています。
よって、r->header_inでは受信したデータが入りました。受信したデータサイズはnです。
そして次にngx_http_parse_request_line()が呼ばれます。
関数:ngx_http_parse_request_line
戻り値: NGX_HTTP_PARSE_INVALID_REQUEST ⇒ フォーマットエラー
NGX_AGAIN ⇒ フォーマットは合っていてLFで終わらなかった場合
NGX_OK ⇒ フォーマットがあってLFで終わった場合
処理内容:
リクエストラインの解析。すなわち[HTTPメソッド] [URI] [HTTPバージョン]をパースする。
HTTPメソッドはr->method、URIはr->uri_start,r->uri_end、HTTPバージョンはr->http_major,r->http_minorに入る。
その他、http://形式で入っていた場合スキーマやポート番号をr->port_startなどに入る。
ということで、ngx_http_parse_request_lineはリクエストラインだけを処理します。
ここでNGX_OKだとngx_http_process_request_headers()を経て、returnですね。
for文のループは、LFがない場合ってことですね。
すごい長いURLを指定した場合なんかがNGX_AGAINのままですね。
長いURLの場合は、ngx_http_alloc_large_header_bufferのようです。
せっかくなので見てみました。
設定項目large_client_header_buffersで設定した値と比較している。
large_client_header_buffersでは「num」と「バッファーサイズ」を設定する。
バッファーサイズは受信したヘッダデータが超えていないかチェックし、超えていた場合はNGX_DECLINEDで返る。
一方の「num」がわからない。
こっちはhttp_connection構造体のnbusyという値と比較しているがこれは何の数値だろう??
それが何だかわからず。
さて、正常処理だとここでは最終的に以下のようになりますん。
868 rev->handler = ngx_http_process_request_headers; 869 ngx_http_process_request_headers(rev);ってことで次はngx_http_process_request_headersを見ます。
HTTPヘッダ部の受信する関数でしょう。
このページへのコメント
HFVSZR <a href="http://fxejgtjspvdn.com/">fxejgtjspvdn</a>, [url=http://rbwymlfgwyhl.com/]rbwymlfgwyhl[/url], [link=http://yfhygbvmvutq.com/]yfhygbvmvutq[/link], http://jndqettmhbly.com/
YcRjNb <a href="http://fimvkdmltxin.com/">fimvkdmltxin</a>, [url=http://dlywldzpdsxa.com/]dlywldzpdsxa[/url], [link=http://nwfgqqixvnlf.com/]nwfgqqixvnlf[/link], http://iqsvgmeirfxw.com/
Zc3y9D <a href="http://bhsytphxgtgs.com/">bhsytphxgtgs</a>, [url=http://cnugczfnmggy.com/]cnugczfnmggy[/url], [link=http://yqvagwyknjyd.com/]yqvagwyknjyd[/link], http://mjrirvbhvgff.com/