Nginx:處理HTTP請求


參考資料<深入理解Nginx>(陶輝)

 

 

處理HTTP請求

接着上一次的內容,本次將說明HTTP框架是如何召集負責具體功能的各HTTP模塊合作處理請求的。

在http://www.cnblogs.com/runnyu/p/4918135.html的最后是通過ngx_http_process_request方法開始處理請求的,該方法流程如下圖

2.設置讀、寫事件的回調方法為ngx_http_request_handler方法,請求的后續處理都是通過ngx_http_request_handler方法進行的。

6.設置ngx_http_request_t結構體的write_event_handler成員為ngx_http_core_run_phases方法。該方法可能會被多次調度來完成HTTP請求的處理。

7.調用ngx_http_core_run_phases回調方法,該方法執行流程如下

ngx_http_request_t結構體中的phase_handler成員(處理流程的核心)將決定執行到哪一階段,關於該成員跟其相關的數據結構可以查看http://www.cnblogs.com/runnyu/p/4910952.html。

該回調方法的源碼如下

void ngx_http_core_run_phases(ngx_http_request_t *r)
{
    ngx_int_t rc;
    ngx_http_phase_handler_t *ph;
    
    cmcf=ngx_http_get_module_man_conf(r,ngx_http_core_module);
    ph=cmcf->phase_engine.handlers;
    
    while(ph[phase_handler].checker){
        rc=ph[r->phase_handler].checker(r,&ph[r->phase_hanlder]);
        if(rc==NGX_OK){
            return;
        }
    }
}

只有當相應的checker方法返回NGX_OK時才將控制權交還給Nginx的事件模塊,否則將繼續執行(checker方法中會修改phase_handler成員以向下執行)。

當這個請求上對應的事件再次觸發時,HTTP框架將回調ngx_http_request_handler方法開始處理請求(上面已經設置了該方法為其讀、寫事件的回調方法)。

下圖是ngx_http_request_handler方法的流程

2.如果當前事件可寫,將調用ngx_http_reqeust_t結構體中的write_event_handler方法。該方法在上面已經設置為ngx_http_core_run_phases,可見該方法會被多次調用。

 

 

Checker方法

checker方法是HTTP框架定義的,每一個HTTP處理階段對應着相應着一個checker方法(有的階段的checker方法一樣),handler方法只有在checker方法中調用。

checker方法的主要任務在於,根據phase_handler執行某個HTTP模塊實現的回調方法,並根據方法的返回值決定:

1.當前階段是否已經結束

2.下次要執行的回調方法是哪一個

3.是立刻執行下一個回調方法還是先把控制權交還給epoll

下面介紹HTTP框架中其中兩個checker方法的介紹

 

ngx_http_core_generic_phase

在前面的http://www.cnblogs.com/runnyu/p/4910952.html下面有該方法的介紹,下面只給出該方法的流程圖

可見,checker方法主要是根據handler方法的返回值來改變phase_handler的值以用來控制handler方法的執行順序的。

 

ngx_http_core_content_phase

ngx_http_core_content_phase是NGX_HTTP_CONTENT_PHASE階段的checker方法。是我們開發HTTP模塊時最常用的一個階段。

其余10個階段中各HTTP模塊的handler方法都是放在全局ngx_http_core_main_conf_t結構體中,而該階段的handler方法則可以放在ngx_http_core_conf_t結構體中,這就是按需掛載的基礎

typedef struct ngx_http_core_loc_conf_s ngx_http_core_loc_conf_t
struct
ngx_http_core_loc_conf_s { ... ngx_http_handler_pt handler; ... }

在我們最初的開發的HTTP模塊中:http://www.cnblogs.com/runnyu/p/4871866.html

當檢測到mytest配置項后,調用ngx_http_mytest方法將上面ngx_http_core_loc_conf_t的handler成員設置為自己的handler函數,實現了按需掛載。

事實上,在NGX_HTTP_FIND_CONFIG_PHASE階段就會把ngx_http_request_t結構體的content_handler成員設置為匹配請求URI的location下的ngx_http_core_loc_conf_t結構體的handler成員。

下面是該checker方法的流程圖,可以看出是如何實現按需掛載的

 

 

處理HTTP包體

在接收完HTTP頭部后,就開始調用各HTTP模塊處理請求了,然后由HTTP模塊決定如何處理包體(handler函數)。

1.接收包體

ngx_int_t ngx_http_read_client_request_body(ngx_http_request *r,ngx_http_client_body_handler_pt post_handler);
typedef void (*ngx_http_client_body_handler_pt) (ngx_http_request_t *r);

接收到的包體保存在ngx_http_reqeust_body_t中,一般調用該函數的handler函數會接着返回NGX_DONE。

在完成接收動作之后,會調用post_handler函數繼續處理請求。

 

2.放棄接收包體(Nginx必須接收包體,但不做處理)

ngx_int ngx_http_discard_reqeust_body(ngx_http_request_t *r);

調用該函數的handler函數繼續處理請求,Nginx會異步地接收跟丟棄包體。

 

 

發送HTTP響應

顯然,發送HTTP響應也是在handler函數中調用的。

1.發送響應頭

ngx_int_t ngx_http_send_header(ngx_http_request_t *r);

該方法會異步地根據ngx_http_reqeust_t中的header_out成員將HTTP頭部發送給客戶端(經過各個過濾模塊)。

 

2.發送響應體

ngx_int_t ngx_http_output_filter(ngx_http_request_t *r,ngx_chain_t *in);

該方法會異步地根據參數in將HTTP響應體發送給客戶端(經過各個過濾模塊)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM