




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年江蘇省文化和旅游廳下屬事業(yè)單位真題
- 激情奉獻(xiàn)行業(yè)月度個(gè)人工作熱情計(jì)劃
- 2024年貴州省監(jiān)獄管理局下屬事業(yè)單位真題
- 網(wǎng)絡(luò)安全事件案例及試題及答案
- 2024年河南鄭州格力在校生招聘筆試真題
- 2025年軟件設(shè)計(jì)師考試實(shí)例題目及試題及答案
- 湖北省恩施州恩施市2025屆數(shù)學(xué)八下期末達(dá)標(biāo)檢測模擬試題含解析
- 2025年軟考軟件設(shè)計(jì)師關(guān)注焦點(diǎn)試題及答案
- 軟件設(shè)計(jì)師在項(xiàng)目管理中的職責(zé)與角色試題及答案
- 代碼查詢與版本控制的使用技巧試題及答案
- 三年級數(shù)學(xué)《認(rèn)識分?jǐn)?shù)》
- 深度解剖華為虛擬股權(quán)激勵(lì)方案最全版含持股比例
- 醫(yī)學(xué)康復(fù)治療技術(shù)作業(yè)治療課件
- 兒科品管圈成果匯報(bào)提高手腕帶佩戴率課件
- 住院患者健康教育計(jì)劃執(zhí)行單
- 中考?xì)v史 (世界現(xiàn)代史)
- 容重器測量結(jié)果的不確定度評定
- 用戶滿意度調(diào)查表(產(chǎn)品與服務(wù)類)
- 電子樣冊三菱電機(jī)水源機(jī)wywr2
- 小學(xué)英語自然拼讀課件
- 七年級第一節(jié)語文課(課堂PPT)
評論
0/150
提交評論