Nginx Learing - ngx_http_request_t 結構體

Nginx學習-ngx_http_request_t 結構體

// http處理的核心數據結構
// 保存有所有http模塊的配置、ctx數據、請求頭、請求體
// 讀寫事件的處理函數
struct ngx_http_request_s {
    // 結構體的“簽名”,C程序裏的常用手段,用特殊字符來標記結構體
    uint32_t                          signature;         /* "HTTP" */

    // 請求對應的連接對象,裏面有log用於記錄日誌
    // 裏面還有讀寫事件read/write
    // 使用它來與客戶端通信收發數據
    ngx_connection_t                 *connection;

    // 保存有所有http模塊的配置、ctx數據
    // 使用ngx_http_get_module_ctx獲取ctx
    // 是一個數組,裏面存儲的是void*
    void                            **ctx;

    // 使用ngx_http_get_module_main_conf訪問
    // 都是一維數組,裏面存儲的是void*
    void                            **main_conf;
    void                            **srv_conf;
    void                            **loc_conf;

    // 讀事件的處理函數
    // 隨着處理的階段不同會變化
    // ngx_http_discarded_request_body_handler:丟棄請求體
    // ngx_http_block_reading:忽略讀事件,即不讀取數據
    ngx_http_event_handler_pt         read_event_handler;

    // 寫事件的處理函數
    // 寫最開始是ngx_http_empty_handler
    // 然後是ngx_http_core_run_phases
    // 當進入content階段調用location handler後變成ngx_http_request_empty_handler
    // 最後是ngx_http_set_write_handler
    ngx_http_event_handler_pt         write_event_handler;

#if (NGX_HTTP_CACHE)
    ngx_http_cache_t                 *cache;
#endif

    // 連接後端upstream的數據結構
    ngx_http_upstream_t              *upstream;
    ngx_array_t                      *upstream_states;
                                         /* of ngx_http_upstream_state_t */

    // 請求的內存池,請求結束時會回收
    ngx_pool_t                       *pool;

    // 緩衝區,用於讀取請求頭
    // 如果有請求體數據,也會都讀到這裏
    ngx_buf_t                        *header_in;

    // 請求頭結構體
    // 裏面用鏈表存儲了所有的頭,也可以用指針快速訪問常用頭
    ngx_http_headers_in_t             headers_in;

    // 響應頭結構體
    // 裏面有狀態碼/狀態行和響應頭鏈表
    ngx_http_headers_out_t            headers_out;

    // 讀取並存儲請求體
    // 指針的形式只有在需要的時候才分配內存
    // 相關函數ngx_http_discard_request_body/ngx_http_read_client_request_body
    ngx_http_request_body_t          *request_body;

    // 延遲關閉的時間點,用於ngx_http_discarded_request_body_handler
    // 可以在這之前接收數據
    time_t                            lingering_time;

    // 請求開始的時間,可用於限速
    time_t                            start_sec;
    ngx_msec_t                        start_msec;

    // 從請求頭解析出來的方法
    // r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD)
    ngx_uint_t                        method;

    // http協議版本號,通常不需要關心
    ngx_uint_t                        http_version;

    // 請求行字符串
    ngx_str_t                         request_line;

    // uri地址,不含參數,即$uri
    ngx_str_t                         uri;

    // uri後的參數,不含問號,即$args
    ngx_str_t                         args;

    // uri裏文件的擴展名
    ngx_str_t                         exten;

    // 原始請求uri,未解碼,即$request_uri
    ngx_str_t                         unparsed_uri;

    // 請求的方法名字符串,例如GET/POST/DELETE
    // 因爲字符串比較慢,所以應該儘量用method來判斷方法
    ngx_str_t                         method_name;

    // http協議字符串,通常不需要關注
    ngx_str_t                         http_protocol;

    // 發送的數據鏈表
    // 所有的header、body數據都會存在這裏
    ngx_chain_t                      *out;

    // 指向主請求,即由客戶端發起的請求
    // 如果沒有子請求,那麼r == main
    ngx_http_request_t               *main;

    // 父請求,如果是子請求,那麼指向產生它的父請求
    // 如果是主請求,指針是空
    ngx_http_request_t               *parent;

    // 子請求處理相關的數據結構
    ngx_http_postponed_request_t     *postponed;
    ngx_http_post_subrequest_t       *post_subrequest;
    ngx_http_posted_request_t        *posted_requests;

    // 執行ngx_http_core_run_phases時的重要參數,標記在引擎數組裏的位置
    // 可以理解爲一個執行的“遊標”
    ngx_int_t                         phase_handler;

    // 重要!!
    // 本location專門的內容處理函數,產生響應內容
    // 在ngx_http_update_location_config裏設置
    ngx_http_handler_pt               content_handler;

    // access階段裏設置的是否允許訪問
    ngx_uint_t                        access_code;

    // 變量值數組,每個請求都不同
    // 1.11.10增加了prefix_variables
    ngx_http_variable_value_t        *variables;

#if (NGX_PCRE)
    ngx_uint_t                        ncaptures;
    int                              *captures;
    u_char                           *captures_data;
#endif

    // 限速用
    // 可以用$limit_rate來隨時改變
    size_t                            limit_rate;

    // 多少字節之後開始限速
    // 未提供$limit_rate,但可以參考$limit_rate添加
    // 在ngx_http_variables.c
    size_t                            limit_rate_after;

    // 用處不大,僅用於計算body_bytes_sent變量
    // sent = r->connection->sent - r->header_size;
    /* used to learn the Apache compatible response length without a header */
    size_t                            header_size;

    // 收到的請求數據總長度,即header+body
    off_t                             request_length;

    // 出錯的狀態碼,如果設置了會代替headers_out.status
    // 見ngx_http_send_header()
    ngx_uint_t                        err_status;

    ngx_http_connection_t            *http_connection;
    ngx_http_v2_stream_t             *stream;

    // 記錄錯誤日誌時可以調用的函數
    // 在ngx_http_log_error裏調用
    ngx_http_log_handler_pt           log_handler;

    // 清理結構體鏈表,結束時會逐個調用
    // 與內存池的清理調用時機不同
    ngx_http_cleanup_t               *cleanup;


    // 引用計數,丟棄/讀取請求體/發起子請求都會增加
    // 表示當前請求有其他關聯的操作,不能隨意關閉
    // 在http_close裏會檢查count,如果大於1只減少,不會真正關閉
    // 1.8裏是8位,1.10改爲16位
    unsigned                          count:16;

    // 子請求數量,最多不能超過50個
    unsigned                          subrequests:8;

    // 請求的阻塞數量,用於線程池
    // 當發起一個多線程task時需要增加
    // task結束時需要減少
    unsigned                          blocked:8;

    unsigned                          aio:1;

    unsigned                          http_state:4;

    /* URI with "/." and on Win32 with "//" */
    unsigned                          complex_uri:1;

    /* URI with "%" */
    unsigned                          quoted_uri:1;

    /* URI with "+" */
    unsigned                          plus_in_uri:1;

    /* URI with " " */
    unsigned                          space_in_uri:1;

    unsigned                          invalid_header:1;

    unsigned                          add_uri_to_alias:1;
    unsigned                          valid_location:1;
    unsigned                          valid_unparsed_uri:1;

    // uri是否被改寫的標誌位
    // 在ngx_http_core_post_rewrite_phase裏檢查
    unsigned                          uri_changed:1;

    // uri改寫的次數
    // 在ngx_http_core_post_rewrite_phase裏檢查
    unsigned                          uri_changes:4;

    unsigned                          request_body_in_single_buf:1;

    // 是否把請求體數據存入文件,與request_body_no_buffering相反
    unsigned                          request_body_in_file_only:1;

    unsigned                          request_body_in_persistent_file:1;
    unsigned                          request_body_in_clean_file:1;
    unsigned                          request_body_file_group_access:1;
    unsigned                          request_body_file_log_level:3;

    // 0-緩存請求體數據
    // 1-不緩存請求體數據
    unsigned                          request_body_no_buffering:1;

    // 要求upstream的數據都在內存裏,方便處理
    unsigned                          subrequest_in_memory:1;

    unsigned                          waited:1;

#if (NGX_HTTP_CACHE)
    unsigned                          cached:1;
    unsigned                          cache_updater:1;
#endif

#if (NGX_HTTP_GZIP)
    unsigned                          gzip_tested:1;
    unsigned                          gzip_ok:1;
    unsigned                          gzip_vary:1;
#endif

    unsigned                          proxy:1;
    unsigned                          bypass_cache:1;
    unsigned                          no_cache:1;

    /*
     * instead of using the request context data in
     * ngx_http_limit_conn_module and ngx_http_limit_req_module
     * we use the single bits in the request structure
     */
    unsigned                          limit_conn_set:1;
    unsigned                          limit_req_set:1;

#if 0
    unsigned                          cacheable:1;
#endif

    unsigned                          pipeline:1;

    // 兩種含義,如果請求頭有chunked那麼置1,表示請求體長度不確定
    // 如果響應頭無content_length_n,那麼表示響應體長度不確定,是chunked
    unsigned                          chunked:1;

    // 只有頭的標誌位
    // ngx_http_header_filter_module裏檢查,如果方法是head則置1
    unsigned                          header_only:1;

    // 是否keep alive
    unsigned                          keepalive:1;

    // 延後關閉標誌
    unsigned                          lingering_close:1;

    // 丟棄請求體的標誌,在ngx_http_discard_request_body裏設置
    unsigned                          discard_body:1;

    // 正在讀取請求體,在ngx_http_read_client_request_body裏設置
    unsigned                          reading_body:1;

    // 是否是內部請求,即子請求
    unsigned                          internal:1;

    unsigned                          error_page:1;
    unsigned                          filter_finalize:1;
    unsigned                          post_action:1;
    unsigned                          request_complete:1;
    unsigned                          request_output:1;

    // 是否已經發送了頭,如果已經發送則不能再次設置或發送頭
    unsigned                          header_sent:1;

    unsigned                          expect_tested:1;
    unsigned                          root_tested:1;
    unsigned                          done:1;
    unsigned                          logged:1;

    // 發送數據是否已經被緩衝,即沒有完全發送完
    unsigned                          buffered:4;

    unsigned                          main_filter_need_in_memory:1;
    unsigned                          filter_need_in_memory:1;
    unsigned                          filter_need_temporary:1;
    unsigned                          allow_ranges:1;
    unsigned                          subrequest_ranges:1;
    unsigned                          single_range:1;
    unsigned                          disable_not_modified:1;
    unsigned                          stat_reading:1;
    unsigned                          stat_writing:1;
    unsigned                          stat_processing:1;

    unsigned                          health_check:1;

    /* used to parse HTTP headers */

    ngx_uint_t                        state;

    ngx_uint_t                        header_hash;
    ngx_uint_t                        lowcase_index;
    u_char                            lowcase_header[NGX_HTTP_LC_HEADER_LEN];

    u_char                           *header_name_start;
    u_char                           *header_name_end;
    u_char                           *header_start;
    u_char                           *header_end;

    /*
     * a memory that can be reused after parsing a request line
     * via ngx_http_ephemeral_t
     */

    u_char                           *uri_start;
    u_char                           *uri_end;
    u_char                           *uri_ext;
    u_char                           *args_start;
    u_char                           *request_start;
    u_char                           *request_end;
    u_char                           *method_end;
    u_char                           *schema_start;
    u_char                           *schema_end;
    u_char                           *host_start;
    u_char                           *host_end;
    u_char                           *port_start;
    u_char                           *port_end;

    // http的主次版本號
    unsigned                          http_minor:16;
    unsigned                          http_major:16;
};

參考:
https://github.com/chronolaw/annotated_nginx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章