HTTP協(xié)議的結(jié)構(gòu)_第1頁
HTTP協(xié)議的結(jié)構(gòu)_第2頁
HTTP協(xié)議的結(jié)構(gòu)_第3頁
HTTP協(xié)議的結(jié)構(gòu)_第4頁
HTTP協(xié)議的結(jié)構(gòu)_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、HTTP協(xié)議的結(jié)構(gòu)2004-11-08 09:18:54     我來說兩句       收藏    我要投稿 Internet是由各個(gè)協(xié)議連接起來的,而我們現(xiàn)在使用最廣的莫過于HTTP協(xié)議了,也就是超文本傳輸協(xié)議,與FTP(文件傳輸協(xié)議)不同,由于主要用于超文本傳輸,因此HTTP協(xié)議顯得更簡單一點(diǎn)。今天我們來介紹一下HTTP協(xié)議的基本格式。在這里,我們所談及的HTTP協(xié)議以HTTP/1.1為標(biāo)準(zhǔn),并且使用Net Vampire Pro 4.0來取得與HTTP服務(wù)器的通信Log,您也可

2、以使用其它的HTTP下載工具來取得通信Log。在HTTP協(xié)議中,服務(wù)端是指提供HTTP服務(wù)的部分,客戶端是指你使用的瀏覽器或者下載工具等等。在通訊時(shí),由客戶端發(fā)出請求連接,服務(wù)端建立連接;然后,客戶端發(fā)出HTTP請求(Request),服務(wù)端返回響應(yīng)信息(Respond),由此完成一個(gè)HTTP操作。我們來通過一個(gè)例子來了解這個(gè)過程:(以下是Net Vampire進(jìn)行的一次連接,以下紅色字體為作者添加)P 01-5-26 16:10:43 Connecting to . /連接服務(wù)器P 01-5-26 16:10:44 Connected to 48 /解析IP地址,以下為

3、HTTP操作S 01-5-26 16:10:44 GET /minift/epretty/pretty.zip HTTP/1.1 /請求行(Request Line),表示使用GET方式取得文件,使用HTTP/1.1協(xié)議 /以下為請求頭部(Request Head)S 01-5-26 16:10:44 Connection: close /表示非持續(xù)性連接S 01-5-26 16:10:44 Host: /主機(jī)名稱S 01-5-26 16:10:44 Accept: */* /接受的數(shù)據(jù)類型S 01-5-26 16:10:44 Pragma: no-cache /參數(shù)(與以前的服務(wù)器兼容)S

4、01-5-26 16:10:44 Cache-Control: no-cache /不使用緩存S 01-5-26 16:10:44 Referer: /從該網(wǎng)址轉(zhuǎn)來S 01-5-26 16:10:44 User-Agent: Mozilla/4.04 en (Win95; I ;Nav)/客戶端標(biāo)識S 01-5-26 16:10:44 Cookie: AdId=ACDDAAAAAAAS 01-5-26 16:10:44 /以下為RespondR 01-5-26 16:10:47 HTTP/1.0 200 OK /響應(yīng)行(Respond Line),服務(wù)器使用HTTP/1.0協(xié)議,狀態(tài)值(Sta

5、tus Code)為200,狀態(tài)為OK,表示文件可以讀取R 01-5-26 16:10:47 Date: Sat, 26 May 2001 08:15:54 GMT /現(xiàn)在的時(shí)間,用格林威治時(shí)間表示R 01-5-26 16:10:47 Server: Apache/1.3.14 (Unix) mod_layout/2.9.9 /服務(wù)器類型R 01-5-26 16:10:47 Last-Modified: Fri, 04 May 2001 02:42:56 GMT /文件最后更新時(shí)間R 01-5-26 16:10:47 ETag: "e614cf-37965-3af21730"

6、;R 01-5-26 16:10:47 Accept-Ranges: bytes /接受的范圍單位R 01-5-26 16:10:47 Content-Length: 227685 /文件長度 R 01-5-26 16:10:47 Content-Type: application/zip /MIME類型R 01-5-26 16:10:47 X-Cache: MISS from shca8R 01-5-26 16:10:47 X-Cache-Lookup: MISS from shca8:80R 01-5-26 16:10:47 Connection: close /表示文件傳輸完畢就關(guān)閉連接

7、。R 01-5-26 16:10:47 /以下為文件傳輸P 01-5-26 16:10:47 Data transfer started 下面來講解使用的格式(LRCF=1310,即回車,SP=SPACE,即空格)Request:協(xié)議方式 SP 文件URI SP 協(xié)議版本 LRCF (請求行)(以下為頭部)頭部類型 : 頭部值 LRCF頭部類型 : 頭部值 LRCF頭部類型 : 頭部值 LRCF. LRCF 表示頭部結(jié)束(如果有體部,以下為體部)Respond:協(xié)議版本 SP 狀態(tài)值 SP 狀態(tài)描述 LRCF (響應(yīng)行)(以下為頭部)頭部類型 : 頭部值 LRCF頭部類型 : 頭部值 LRCF

8、頭部類型 : 頭部值 LRCF. LRCF 表示頭部結(jié)束(如果有體部,以下為體部)由上可見,請求與相應(yīng)的格式只有部分不同,是很容易理解的,現(xiàn)在你應(yīng)該基本了解HTTP協(xié)議了吧,也能看懂那些通信Log了吧,下一次我們講專門講解在響應(yīng)行中的狀態(tài)值含義及一些特殊情況。 3.1如何調(diào)用HTTP模塊2013-03-27 12:03 陶輝 機(jī)械工業(yè)出版社 字號:T | T深入理解Nginx:模塊開發(fā)與架構(gòu)解析第3章開發(fā)一個(gè)簡單的HTTP模塊,本章講述了如何開發(fā)一個(gè)基本的HTTP模塊,這里除了獲取請求的包體外沒有涉及異步處理問題。本節(jié)為大家介紹。 AD: 51CTO學(xué)院:IT精品課程在線看! 第二部分 如何編

9、寫HTTP模塊本部分內(nèi)容第3章開發(fā)一個(gè)簡單的HTTP模塊第4章配置、error日志和請求上下文第5章訪問第三方服務(wù)第6章開發(fā)一個(gè)簡單的HTTP過濾模塊第7章Nginx提供的高級數(shù)據(jù)結(jié)構(gòu)第3章開發(fā)一個(gè)簡單的HTTP模塊當(dāng)通過開發(fā)HTTP模塊來實(shí)現(xiàn)產(chǎn)品功能時(shí),是可以完全享用Nginx的優(yōu)秀設(shè)計(jì)所帶來的、與官方模塊相同的高并發(fā)特性的。不過,如何開發(fā)一個(gè)充滿異步調(diào)用、無阻塞的HTTP模塊呢?首先,需要把程序嵌入到Nginx中,也就是說,最終編譯出的二進(jìn)制程序Nginx要包含我們的代碼(見3.3節(jié));其次,這個(gè)全新的HTTP模塊要能介入到HTTP請求的處理流程中(具體參見3.1節(jié)、3.4節(jié)、3.5節(jié))。

10、滿足上述兩個(gè)前提后,我們的模塊才能開始處理HTTP請求,但在開始處理請求前還需要先了解一些Nginx框架定義的數(shù)據(jù)結(jié)構(gòu)(見3.2節(jié)),這是后面必須要用到的;正式處理請求時(shí),還要可以獲得Nginx框架接收、解析后的用戶請求信息(見3.6節(jié));業(yè)務(wù)執(zhí)行完畢后,則要考慮發(fā)送響應(yīng)給用戶(見3.7節(jié)),包括將磁盤中的文件以HTTP包體的形式發(fā)送給用戶(見3.8節(jié))。本章最后會討論如何用C+語言來編寫HTTP模塊,這雖然不是Nginx官方倡導(dǎo)的方式,但C+向前兼容C語言,使用C+語言開發(fā)的模塊還是可以很容易地嵌入到Nginx中。本章不會深入探討HTTP模塊與Nginx的各個(gè)核心模塊是如何配合工作的,而且這

11、部分提到的每個(gè)接口將只涉及用法而不涉及實(shí)現(xiàn)原理,在第3部分我們才會進(jìn)一步闡述本章提到的許多接口是如何實(shí)現(xiàn)異步訪問的。3.1如何調(diào)用HTTP模塊在開發(fā)HTTP模塊前,首先需要了解典型的HTTP模塊是如何介入Nginx處理用戶請求流程的。圖3-1是一個(gè)簡化的時(shí)序圖,這里省略了許多異步調(diào)用,忽略了多個(gè)不同的HTTP處理階段,僅標(biāo)識了在一個(gè)典型請求的處理過程中主要模塊被調(diào)用的流程,以此幫助讀者理解HTTP模塊如何處理用戶請求。完整的流程將在第11章中詳細(xì)介紹。從圖3-1中看到,worker進(jìn)程會在一個(gè)for循環(huán)語句里反復(fù)調(diào)用事件模塊檢測網(wǎng)絡(luò)事件。當(dāng)事件模塊檢測到某個(gè)客戶端發(fā)起的TCP請求時(shí)(接收到SY

12、N包),將會為它建立TCP連接,成功建立連接后根據(jù)nginx.conf文件中的配置會交由HTTP框架處理。HTTP框架會試圖接收完整的HTTP頭部,并在接收到完整的HTTP頭部后將請求分發(fā)到具體的HTTP模塊中處理。這種分發(fā)策略是多樣化的,其中最常見的是根據(jù)請求的URI和nginx.conf里location配置項(xiàng)的匹配度來決定如何分發(fā)(本章的例子正是應(yīng)用這種分發(fā)策略,在第10章中會介紹其他分發(fā)策略)。HTTP模塊在處理請求的結(jié)束時(shí),大多會向客戶端發(fā)送響應(yīng),此時(shí)會自動地依次調(diào)用所有的HTTP過濾模塊,每個(gè)過濾模塊可以根據(jù)配置文件決定自己的行為。例如,gzip過濾模塊根據(jù)配置文件中的gzip o

13、n|off來決定是否壓縮響應(yīng)。HTTP處理模塊在返回時(shí)會將控制權(quán)交還給HTTP框架,如果在返回前設(shè)置了subrequest,那么HTTP框架還會繼續(xù)異步地調(diào)用適合的HTTP模塊處理子請求。開發(fā)HTTP模塊時(shí),首先要注意的就是HTTP框架到具體的HTTP模塊間數(shù)據(jù)流的傳遞,以及開發(fā)的HTTP模塊如何與諸多的過濾模塊協(xié)同工作(第10章、第11章會詳細(xì)介紹HTTP框架)。下面正式進(jìn)入HTTP模塊的開發(fā)環(huán)節(jié)。 【責(zé)任編輯:b深入理解Nginx:模塊開發(fā)與架構(gòu)解析第3章開發(fā)一個(gè)簡單的HTTP模塊,本章講述了如何開發(fā)一個(gè)基本的HTTP模塊,這里除了獲取請求的包體外沒有涉及異步處理問題。本節(jié)為大家

14、介紹定義自己的HTTP模塊。 3.4HTTP模塊的數(shù)據(jù)結(jié)構(gòu)(1)定義HTTP模塊方式很簡單,例如:1. ngx_module_t ngx_http_mytest_module; 其中,ngx_module_t 是一個(gè)Nginx模塊的數(shù)據(jù)結(jié)構(gòu)(詳見8.2節(jié))。下面來分析一下Nginx模塊中所有的成員,如下所示:1. typedef struct ngx_module_s      ngx_module_t;  2. struct ngx_module_s   

15、;3.     /* 下面的ctx_index、index、spare0、spare1、spare2、spare3、version變量不需要在定義時(shí)賦值,可以用Nginx準(zhǔn)備好的宏NGX_MODULE_V1來定義,它已經(jīng)定義好了這7個(gè)值。  4. #define NGX_MODULE_V1          0, 0, 0, 0, 0, 0, 1  5. &

16、#160;6.     對于一類模塊(由下面的type成員決定類別)而言,ctx_index表示當(dāng)前模塊在這類模塊中的序號。這個(gè)成員常常是由管理這類模塊的一個(gè)Nginx核心模塊設(shè)置的,對于所有的HTTP模塊而言,ctx_index是由核心模塊ngx_http_module設(shè)置的。ctx_index非常重要,Nginx的模塊化設(shè)計(jì)非常依賴于各個(gè)模塊的順序,它們既用于表達(dá)優(yōu)先級,也用于表明每個(gè)模塊的位置,借以幫助Nginx框架快速獲得某個(gè)模塊的數(shù)據(jù)(HTTP框架設(shè)置ctx_index的過程參見10.7節(jié))*/  7.   

17、60; ngx_uint_t            ctx_index;  8.  9.     /*index表示當(dāng)前模塊在ngx_modules數(shù)組中的序號。注意,ctx_index表示的是當(dāng)前模塊在一類模塊中的序號,而index表示當(dāng)前模塊在所有模塊中的序號,它同樣關(guān)鍵。Nginx啟動時(shí)會根據(jù)ngx_modules數(shù)組設(shè)置各模塊的index值。例如:  10. ngx_max_module&

18、#160;= 0;  11. for (i = 0; ngx_modulesi; i+)   12.     ngx_modulesi->index = ngx_max_module+;  13.  14. */  15.     ngx_uint_t          &

19、#160; index;  16.  17.     /spare系列的保留變量,暫未使用  18.     ngx_uint_t            spare0;  19.     ngx_uint_t        

20、60;   spare1;  20.     ngx_uint_t            spare2;  21.     ngx_uint_t            spare3;  22.   &

21、#160; /模塊的版本,便于將來的擴(kuò)展。目前只有一種,默認(rèn)為1  23.     ngx_uint_t            version;  24.  25.     /*ctx用于指向一類模塊的上下文結(jié)構(gòu)體,為什么需要ctx呢?因?yàn)榍懊嬲f過,Nginx模塊有許多種類,不同類模塊之間的功能差別很大。例如,事件類型的模塊主要處理I/O事件相關(guān)的功能,HT

22、TP類型的模塊主要處理HTTP應(yīng)用層的功能。這樣,每個(gè)模塊都有了自己的特性,而ctx將會指向特定類型模塊的公共接口。例如,在HTTP模塊中,ctx需要指向ngx_http_module_t結(jié)構(gòu)體*/  26.     void                 *ctx;  27.  28.     /commands將

23、處理nginx.conf中的配置項(xiàng),詳見第4章  29.     ngx_command_t        *commands;  30.  31.     /*type表示該模塊的類型,它與ctx指針是緊密相關(guān)的。在官方Nginx中,它的取值范圍是以下5種:NGX_HTTP_MODULE、NGX_CORE_MODULE、NGX_CONF_MODULE、NGX_EVENT_MODULE、NGX_MAIL_M

24、ODULE。這5種模塊間的關(guān)系參考圖8-2。實(shí)際上,還可以自定義新的模塊類型*/  32.     ngx_uint_t            type;  33.  34.     /*在Nginx的啟動、停止過程中,以下7個(gè)函數(shù)指針表示有7個(gè)執(zhí)行點(diǎn)會分別調(diào)用這7種方法(參見8.4節(jié)8.6節(jié))。對于任一個(gè)方法而言,如果不需要Nginx在某個(gè)時(shí)刻執(zhí)行它,那么簡單地把它

25、設(shè)為NULL空指針即可*/  35.  36.     /*雖然從字面上理解應(yīng)當(dāng)在master進(jìn)程啟動時(shí)回調(diào)init_master,但到目前為止,框架代碼從來不會調(diào)用它,因此,可將init_master設(shè)為NULL */  37.     ngx_int_t           (*init_master)(ngx_log_t *log);  38

26、.     /*init_module回調(diào)方法在初始化所有模塊時(shí)被調(diào)用。在master/worker模式下,這個(gè)階段將在啟動worker子進(jìn)程前完成*/  39.     ngx_int_t           (*init_module)(ngx_cycle_t *cycle);  40. /* init_process回調(diào)方法在正常服務(wù)前被調(diào)用。在master/w

27、orker模式下,多個(gè)worker子進(jìn)程已經(jīng)產(chǎn)生,在每個(gè)worker進(jìn)程的初始化過程會調(diào)用所有模塊的init_process函數(shù)*/  41.     ngx_int_t           (*init_process)(ngx_cycle_t *cycle);  42. /* 由于Nginx暫不支持多線程模式,所以init_thread在框架代碼中沒有被調(diào)用過,設(shè)為NULL*/  43. &#

28、160;   ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);  44. / 同上,exit_thread也不支持,設(shè)為NULL  45.     void             

29、60;  (*exit_thread)(ngx_cycle_t *cycle);  46. /* exit_process回調(diào)方法在服務(wù)停止前調(diào)用。在master/worker模式下,worker進(jìn)程會在退出前調(diào)用它*/  47.     void                (*exit_process)(ngx_cycle_t

30、60;*cycle);  48. / exit_master回調(diào)方法將在master進(jìn)程退出前被調(diào)用  49.     void                (*exit_master)(ngx_cycle_t *cycle);  50.  51.     /*以下8個(gè)spare_hook變量也是

31、保留字段,目前沒有使用,但可用Nginx提供的NGX_MODULE_V1_PADDING宏來填充。看一下該宏的定義:#define NGX_MODULE_V1_PADDING  0, 0, 0, 0, 0, 0, 0, 0*/  52.     uintptr_t             spare_hook0; &#

32、160;53.     uintptr_t             spare_hook1;  54.     uintptr_t             spare_hook2;  55.     

33、uintptr_t             spare_hook3;  56.     uintptr_t             spare_hook4;  57.     uintptr_t    

34、;         spare_hook5;  58.     uintptr_t             spare_hook6;  59.     uintptr_t         &

35、#160;   spare_hook7;  60. ; 定義一個(gè)HTTP模塊時(shí),務(wù)必把type字段設(shè)為NGX_HTTP_MODULE。對于下列回調(diào)方法:init_module、init_process、exit_process、exit_master,調(diào)用它們的是Nginx的框架代碼。換句話說,這4個(gè)回調(diào)方法與HTTP框架無關(guān),即使nginx.conf中沒有配置http .這種開啟HTTP功能的配置項(xiàng),這些回調(diào)方法仍然會被調(diào)用。因此,通常開發(fā)HTTP模塊時(shí)都把它們設(shè)為NULL空指針。這樣,當(dāng)Nginx不作為Web服務(wù)器使用時(shí),不會執(zhí)行HTTP模

36、塊的任何代碼。定義HTTP模塊時(shí),最重要的是要設(shè)置ctx和commands這兩個(gè)成員。對于HTTP類型的模塊來說,ngx_module_t中的ctx指針必須指向ngx_http_module_t接口(HTTP框架的要求)。下面先來分析ngx_http_module_t結(jié)構(gòu)體的成員。 3.4HTTP模塊的數(shù)據(jù)結(jié)構(gòu)(2)HTTP框架在讀取、重載配置文件時(shí)定義了由ngx_http_module_t接口描述的8個(gè)階段,HTTP框架在啟動過程中會在每個(gè)階段中調(diào)用ngx_http_module_t中相應(yīng)的方法。當(dāng)然,如果ngx_http_module_t中的某個(gè)回調(diào)方法設(shè)為NULL空指針,那么H

37、TTP框架是不會調(diào)用它的。 1. typedef struct   2.     /解析配置文件前調(diào)用  3.     ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);  4.     /完成配置文件的解析后調(diào)用  5.     ngx_int_t   

38、;(*postconfiguration)(ngx_conf_t *cf);  6.  7.     /*當(dāng)需要?jiǎng)?chuàng)建數(shù)據(jù)結(jié)構(gòu)用于存儲main級別(直屬于http.塊的配置項(xiàng))的全局配置項(xiàng)時(shí),可以通過create_main_conf回調(diào)方法創(chuàng)建存儲全局配置項(xiàng)的結(jié)構(gòu)體*/  8.     void       *(*create_main_conf)(ngx_conf_t *cf);  9.

39、     /常用于初始化main級別配置項(xiàng)  10.     char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);  11.  12.     /*當(dāng)需要?jiǎng)?chuàng)建數(shù)據(jù)結(jié)構(gòu)用于存儲srv級別(直屬于虛擬主機(jī)server.塊的配置項(xiàng))的配置項(xiàng)時(shí),可以通過實(shí)現(xiàn)create_srv_conf回調(diào)方

40、法創(chuàng)建存儲srv級別配置項(xiàng)的結(jié)構(gòu)體*/  13.     void       *(*create_srv_conf)(ngx_conf_t *cf);  14.     / merge_srv_conf回調(diào)方法主要用于合并main級別和srv級別下的同名配置項(xiàng)  15.     char      

41、; *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);  16.  17.     /*當(dāng)需要?jiǎng)?chuàng)建數(shù)據(jù)結(jié)構(gòu)用于存儲loc級別(直屬于location.塊的配置項(xiàng))的配置項(xiàng)時(shí),可以實(shí)現(xiàn)create_loc_conf回調(diào)方法*/  18.     void       *(*create_loc

42、_conf)(ngx_conf_t *cf);  19.     / merge_loc_conf回調(diào)方法主要用于合并srv級別和loc級別下的同名配置項(xiàng)  20.     char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);  21.  ngx_ht

43、tp_module_t; 不過,這8個(gè)階段的調(diào)用順序與上述定義的順序是不同的。在Nginx啟動過程中,HTTP框架調(diào)用這些回調(diào)方法的實(shí)際順序有可能是這樣的(與nginx.conf配置項(xiàng)有關(guān)):1)create_main_conf2)create_srv_conf3)create_loc_conf4)preconfiguration5)init_main_conf6)merge_srv_conf7)merge_loc_conf8)postconfigurationcommands數(shù)組用于定義模塊的配置文件參數(shù),每一個(gè)數(shù)組元素都是ngx_command_t類型,數(shù)組的結(jié)尾用ngx_nul

44、l_command表示。Nginx在解析配置文件中的一個(gè)配置項(xiàng)時(shí)首先會遍歷所有的模塊,對于每一個(gè)模塊而言,即通過遍歷commands數(shù)組進(jìn)行,另外,在數(shù)組中檢查到ngx_null_command時(shí),會停止使用當(dāng)前模塊解析該配置項(xiàng)。每一個(gè)ngx_command_t結(jié)構(gòu)體定義了自己感興趣的一個(gè)配置項(xiàng): 1. typedef struct ngx_command_s     ngx_command_t;  2. struct ngx_command_s   3.  

45、60;  /配置項(xiàng)名稱,如"gzip"  4.     ngx_str_t             name;  5.     /*配置項(xiàng)類型,type將指定配置項(xiàng)可以出現(xiàn)的位置。例如,出現(xiàn)在server或location中,以及它可以攜帶的參數(shù)個(gè)數(shù)*/  6.     ngx_

46、uint_t            type;  7.     /出現(xiàn)了name中指定的配置項(xiàng)后,將會調(diào)用set方法處理配置項(xiàng)的參數(shù)  8.     char               *(*set)(ngx_conf_t

47、60;*cf, ngx_command_t *cmd, void *conf);  9.     /在配置文件中的偏移量  10.     ngx_uint_t            conf;  11.     /*通常用于使用預(yù)設(shè)的解析方法解析配置項(xiàng),這是配置模塊的一個(gè)優(yōu)秀設(shè)計(jì)。它需要

48、與conf配合使用,在第4章中詳細(xì)介紹*/  12.     ngx_uint_t            offset;  13.     /配置項(xiàng)讀取后的處理方法,必須是ngx_conf_post_t結(jié)構(gòu)的指針  14.     void       

49、60;         *post;  15. ;  16. ngx_null_command只是一個(gè)空的ngx_command_t,如下所示:  17. #define ngx_null_command   ngx_null_string, 0, NULL, 0, 0, NULL  3.5定義自己的HTTP模塊(1)上文中我們了解了定義HTTP模塊時(shí)需要定義哪些成員

50、以及實(shí)現(xiàn)哪些方法,但在定義HTTP模塊前,首先需要確定自定義的模塊應(yīng)當(dāng)在什么樣的場景下開始處理用戶請求,也就是說,先要弄清楚我們的模塊是如何介入到Nginx處理用戶請求的流程中的。從2.4節(jié)中的HTTP配置項(xiàng)意義可知,一個(gè)HTTP請求會被許多個(gè)配置項(xiàng)控制,實(shí)際上這是因?yàn)橐粋€(gè)HTTP請求可以被許多個(gè)HTTP模塊同時(shí)處理。這樣一來,肯定會有一個(gè)先后問題,也就是說,誰先處理請求誰的“權(quán)力”就更大。例如,ngx_http_access_module模塊的deny選項(xiàng)一旦得到滿足后,Nginx就會決定拒絕來自某個(gè)IP的請求,后面的諸如root這種訪問靜態(tài)文件的處理方式是得不到執(zhí)行的。另外,由于同一個(gè)配置

51、項(xiàng)可以從屬于許多個(gè)server、location配置塊,那么這個(gè)配置項(xiàng)將會針對不同的請求起作用。因此,現(xiàn)在面臨的問題是,我們希望自己的模塊在哪個(gè)時(shí)刻開始處理請求?是希望自己的模塊對到達(dá)Nginx的所有請求都起作用,還是希望只對某一類請求(如URI匹配了location后表達(dá)式的請求)起作用?Nginx的HTTP框架定義了非常多的用法,我們有很大的自由來定義自己的模塊如何介入HTTP請求的處理,但本章只想說明最簡單、最常見的HTTP模塊應(yīng)當(dāng)如何編寫,因此,我們這樣定義第一個(gè)HTTP模塊介入Nginx的方式:1)不希望模塊對所有的HTTP請求起作用。2)在nginx.conf文件中的http、se

52、rver或者location塊內(nèi)定義mytest配置項(xiàng),如果一個(gè)用戶請求通過主機(jī)域名、URI等匹配上了相應(yīng)的配置塊,而這個(gè)配置塊下又具有mytest配置項(xiàng),那么希望mytest模塊開始處理請求。在這種介入方式下,模塊處理請求的順序是固定的,即必須在HTTP框架定義的NGX_HTTP_CONTENT_PHASE階段開始處理請求,具體內(nèi)容下文詳述。下面開始按照這種方式定義mytest模塊。首先,定義mytest配置項(xiàng)的處理。從上文中關(guān)于ngx_command_t結(jié)構(gòu)的說明來看,只需要定義一個(gè)ngx_command_t數(shù)組,并設(shè)置在出現(xiàn)mytest配置后的解析方法由ngx_http_mytest“擔(dān)

53、當(dāng)”,如下所示:1. static ngx_command_t  ngx_http_mytest_commands =   2.  3.      ngx_string("mytest"),  4. NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS,  5.     &#

54、160; ngx_http_mytest,  6.       NGX_HTTP_LOC_CONF_OFFSET,  7.       0,  8.       NULL ,  9.  10.       ngx_null_command  11. ; 其中,ngx_h

55、ttp_mytest是ngx_command_t結(jié)構(gòu)體中的set成員(完整定義為char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);),當(dāng)在某個(gè)配置塊中出現(xiàn)mytest配置項(xiàng)時(shí),Nginx將會調(diào)用ngx_http_mytest方法。下面看一下如何實(shí)現(xiàn)ngx_http_mytest方法。1. static char *  2. ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *con

56、f)  3.  4.     ngx_http_core_loc_conf_t  *clcf;  5.  6.     /*首先找到mytest配置項(xiàng)所屬的配置塊,clcf看上去像是location塊內(nèi)的數(shù)據(jù)結(jié)構(gòu),其實(shí)不然,它可以是main、srv或者loc級別配置項(xiàng),也就是說,在每個(gè)http和server內(nèi)也都有一個(gè)ngx_http_core_loc_conf_t結(jié)構(gòu)體*/  7.     clcf

57、60;= ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);  8.  9.     /*HTTP框架在處理用戶請求進(jìn)行到NGX_HTTP_CONTENT_PHASE階段時(shí),如果請求的主機(jī)域名、URI與mytest配置項(xiàng)所在的配置塊相匹配,就將調(diào)用我們實(shí)現(xiàn)的ngx_http_mytest_handler方法處理這個(gè)請求*/  10.     clcf->handler = 

58、;ngx_http_mytest_handler;  11.  12.     return NGX_CONF_OK;  13.  當(dāng)Nginx接收完HTTP請求的頭部信息時(shí),就會調(diào)用HTTP框架處理請求,另外在11.6節(jié)描述的NGX_HTTP_CONTENT_PHASE階段將有可能調(diào)用mytest模塊處理請求。在ngx_http_mytest方法中,我們定義了請求的處理方法為ngx_http_mytest_handler,舉個(gè)例子來說,如果用戶的請求URI是/test/example,而在配置文件中有這

59、樣的location塊: 1. Location /test   2.     mytest;  3.  那么,HTTP框架在NGX_HTTP_CONTENT_PHASE階段就會調(diào)用到我們實(shí)現(xiàn)的ngx_http_mytest_handler方法來處理這個(gè)用戶請求。事實(shí)上,HTTP框架共定義了11個(gè)階段(第三方HTTP模塊只能介入其中的7個(gè)階段處理請求,詳見10.6節(jié)),本章只關(guān)注NGX_HTTP_CONTENT_PHASE處理階段,多數(shù)HTTP模塊都在此階段實(shí)現(xiàn)相關(guān)功能。下面簡單說明一下這11個(gè)

60、階段。1. typedef enum   2.     /在接收到完整的HTTP頭部后處理的HTTP階段  3.     NGX_HTTP_POST_READ_PHASE = 0,  4.  5.     /*在還沒有查詢到URI匹配的location前,這時(shí)rewrite重寫URL也作為一個(gè)獨(dú)立的HTTP階段*/  6.     NGX_HTTP

61、_SERVER_REWRITE_PHASE,  7.  8.     /*根據(jù)URI尋找匹配的location,這個(gè)階段通常由ngx_http_core_module模塊實(shí)現(xiàn),不建議其他HTTP模塊重新定義這一階段的行為*/  9.     NGX_HTTP_FIND_CONFIG_PHASE,  10.  11.     /*在NGX_HTTP_FIND_CONFIG_PHASE階段之后重寫URL的意義與NGX_HTTP_S

62、ERVER_REWRITE_PHASE階段顯然是不同的,因?yàn)檫@兩者會導(dǎo)致查找到不同的location塊(location是與URI進(jìn)行匹配的)*/  12.     NGX_HTTP_REWRITE_PHASE,  13.  14.     /*這一階段是用于在rewrite重寫URL后重新跳到NGX_HTTP_FIND_CONFIG_PHASE階段,找到與新的URI匹配的location。所以,這一階段是無法由第三方HTTP模塊處理的,而僅由ngx_http_core_module模

63、塊使用*/  15.     NGX_HTTP_POST_REWRITE_PHASE,  16.  17.     /處理NGX_HTTP_ACCESS_PHASE階段前,HTTP模塊可以介入的處理階段  18.     NGX_HTTP_PREACCESS_PHASE,  19.  20.     /*這個(gè)階段用于讓HTTP模塊判斷是否允許這個(gè)請求訪問Nginx服務(wù)器 

64、60;21.     NGX_HTTP_ACCESS_PHASE,  22.  23.     /*當(dāng)NGX_HTTP_ACCESS_PHASE階段中HTTP模塊的handler處理方法返回不允許訪問的錯(cuò)誤碼時(shí)(實(shí)際是NGX_HTTP_FORBIDDEN或者NGX_HTTP_UNAUTHORIZED),這個(gè)階段將負(fù)責(zé)構(gòu)造拒絕服務(wù)的用戶響應(yīng)。所以,這個(gè)階段實(shí)際上用于給NGX_HTTP_ACCESS_PHASE階段收尾*/  24.     NGX_

65、HTTP_POST_ACCESS_PHASE,  25.  26.     /*這個(gè)階段完全是為了try_files配置項(xiàng)而設(shè)立的。當(dāng)HTTP請求訪問靜態(tài)文件資源時(shí),try_files配置項(xiàng)可以使這個(gè)請求順序地訪問多個(gè)靜態(tài)文件資源,如果某一次訪問失敗,則繼續(xù)訪問try_files中指定的下一個(gè)靜態(tài)資源。另外,這個(gè)功能完全是在NGX_HTTP_TRY_FILES_PHASE階段中實(shí)現(xiàn)的*/  27.     NGX_HTTP_TRY_FILES_PHASE,  28. 

66、0;29.     /用于處理HTTP請求內(nèi)容的階段,這是大部分HTTP模塊最喜歡介入的階段  30.     NGX_HTTP_CONTENT_PHASE,  31.  32.     /*處理完請求后記錄日志的階段。例如,ngx_http_log_module模塊就在這個(gè)階段中加入了一個(gè)handler處理方法,使得每個(gè)HTTP請求處理完畢后會記錄access_log日志*/  33.     

67、NGX_HTTP_LOG_PHASE  34.  ngx_http_phases; 3.5定義自己的HTTP模塊(2)當(dāng)然,用戶可以在以上11個(gè)階段中任意選擇一個(gè)階段讓mytest模塊介入,但這需要學(xué)習(xí)完第10章、第11章的內(nèi)容,完全熟悉了HTTP框架的處理流程后才可以做到。暫且不管如何實(shí)現(xiàn)處理請求的ngx_http_mytest_handler方法,如果沒有什么工作是必須在HTTP框架初始化時(shí)完成的,那就不必實(shí)現(xiàn)ngx_http_module_t的8個(gè)回調(diào)方法,可以像下面這樣定義ngx_http_module_t接口。1. static ngx_htt

68、p_module_t  ngx_http_mytest_module_ctx =   2.     NULL,                       /* preconfiguration */  3.    &#

69、160;NULL,                   /* postconfiguration */  4.  5.     NULL,                

70、       /* create main configuration */  6.     NULL,                       /* init main co

71、nfiguration */  7.  8.     NULL,                       /* create server configuration */  9.     NULL,

72、60;                      /* merge server configuration */  10.  11.     NULL,          

73、60;        /* create location configuration */  12.     NULL                    /* merge location co

74、nfiguration */  13. ; 最后,定義mytest模塊:1. ngx_module_t  ngx_http_mytest_module =   2.     NGX_MODULE_V1,  3.     &ngx_http_mytest_module_ctx,           /* module context */  4.     ngx_http_mytest_comma

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論