




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、HTTP協(xié)議的結(jié)構(gòu)2004-11-08 09:18:54 我來(lái)說(shuō)兩句 收藏 我要投稿 Internet是由各個(gè)協(xié)議連接起來(lái)的,而我們現(xiàn)在使用最廣的莫過(guò)于HTTP協(xié)議了,也就是超文本傳輸協(xié)議,與FTP(文件傳輸協(xié)議)不同,由于主要用于超文本傳輸,因此HTTP協(xié)議顯得更簡(jiǎn)單一點(diǎn)。今天我們來(lái)介紹一下HTTP協(xié)議的基本格式。在這里,我們所談及的HTTP協(xié)議以HTTP/1.1為標(biāo)準(zhǔn),并且使用Net Vampire Pro 4.0來(lái)取得與HTTP服務(wù)器的通信Log,您也可
2、以使用其它的HTTP下載工具來(lái)取得通信Log。在HTTP協(xié)議中,服務(wù)端是指提供HTTP服務(wù)的部分,客戶端是指你使用的瀏覽器或者下載工具等等。在通訊時(shí),由客戶端發(fā)出請(qǐng)求連接,服務(wù)端建立連接;然后,客戶端發(fā)出HTTP請(qǐng)求(Request),服務(wù)端返回響應(yīng)信息(Respond),由此完成一個(gè)HTTP操作。我們來(lái)通過(guò)一個(gè)例子來(lái)了解這個(gè)過(guò)程:(以下是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 /請(qǐng)求行(Request Line),表示使用GET方式取得文件,使用HTTP/1.1協(xié)議 /以下為請(qǐng)求頭部(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)來(lái)S 01-5-26 16:10:44 User-Agent: Mozilla/4.04 en (Win95; I ;Nav)/客戶端標(biāo)識(shí)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 /文件長(zhǎng)度 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 下面來(lái)講解使用的格式(LRCF=1310,即回車,SP=SPACE,即空格)Request:協(xié)議方式 SP 文件URI SP 協(xié)議版本 LRCF (請(qǐng)求行)(以下為頭部)頭部類型 : 頭部值 LRCF頭部類型 : 頭部值 LRCF頭部類型 : 頭部值 LRCF. LRCF 表示頭部結(jié)束(如果有體部,以下為體部)Respond:協(xié)議版本 SP 狀態(tài)值 SP 狀態(tài)描述 LRCF (響應(yīng)行)(以下為頭部)頭部類型 : 頭部值 LRCF頭部類型 : 頭部值 LRCF
8、頭部類型 : 頭部值 LRCF. LRCF 表示頭部結(jié)束(如果有體部,以下為體部)由上可見(jiàn),請(qǐng)求與相應(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è)出版社 字號(hào):T | T深入理解Nginx:模塊開(kāi)發(fā)與架構(gòu)解析第3章開(kāi)發(fā)一個(gè)簡(jiǎn)單的HTTP模塊,本章講述了如何開(kāi)發(fā)一個(gè)基本的HTTP模塊,這里除了獲取請(qǐng)求的包體外沒(méi)有涉及異步處理問(wèn)題。本節(jié)為大家介紹。 AD: 51CTO學(xué)院:IT精品課程在線看! 第二部分 如何編
9、寫HTTP模塊本部分內(nèi)容第3章開(kāi)發(fā)一個(gè)簡(jiǎn)單的HTTP模塊第4章配置、error日志和請(qǐng)求上下文第5章訪問(wèn)第三方服務(wù)第6章開(kāi)發(fā)一個(gè)簡(jiǎn)單的HTTP過(guò)濾模塊第7章Nginx提供的高級(jí)數(shù)據(jù)結(jié)構(gòu)第3章開(kāi)發(fā)一個(gè)簡(jiǎn)單的HTTP模塊當(dāng)通過(guò)開(kāi)發(fā)HTTP模塊來(lái)實(shí)現(xiàn)產(chǎn)品功能時(shí),是可以完全享用Nginx的優(yōu)秀設(shè)計(jì)所帶來(lái)的、與官方模塊相同的高并發(fā)特性的。不過(guò),如何開(kāi)發(fā)一個(gè)充滿異步調(diào)用、無(wú)阻塞的HTTP模塊呢?首先,需要把程序嵌入到Nginx中,也就是說(shuō),最終編譯出的二進(jìn)制程序Nginx要包含我們的代碼(見(jiàn)3.3節(jié));其次,這個(gè)全新的HTTP模塊要能介入到HTTP請(qǐng)求的處理流程中(具體參見(jiàn)3.1節(jié)、3.4節(jié)、3.5節(jié))。
10、滿足上述兩個(gè)前提后,我們的模塊才能開(kāi)始處理HTTP請(qǐng)求,但在開(kāi)始處理請(qǐng)求前還需要先了解一些Nginx框架定義的數(shù)據(jù)結(jié)構(gòu)(見(jiàn)3.2節(jié)),這是后面必須要用到的;正式處理請(qǐng)求時(shí),還要可以獲得Nginx框架接收、解析后的用戶請(qǐng)求信息(見(jiàn)3.6節(jié));業(yè)務(wù)執(zhí)行完畢后,則要考慮發(fā)送響應(yīng)給用戶(見(jiàn)3.7節(jié)),包括將磁盤中的文件以HTTP包體的形式發(fā)送給用戶(見(jiàn)3.8節(jié))。本章最后會(huì)討論如何用C+語(yǔ)言來(lái)編寫HTTP模塊,這雖然不是Nginx官方倡導(dǎo)的方式,但C+向前兼容C語(yǔ)言,使用C+語(yǔ)言開(kāi)發(fā)的模塊還是可以很容易地嵌入到Nginx中。本章不會(huì)深入探討HTTP模塊與Nginx的各個(gè)核心模塊是如何配合工作的,而且這
11、部分提到的每個(gè)接口將只涉及用法而不涉及實(shí)現(xiàn)原理,在第3部分我們才會(huì)進(jìn)一步闡述本章提到的許多接口是如何實(shí)現(xiàn)異步訪問(wèn)的。3.1如何調(diào)用HTTP模塊在開(kāi)發(fā)HTTP模塊前,首先需要了解典型的HTTP模塊是如何介入Nginx處理用戶請(qǐng)求流程的。圖3-1是一個(gè)簡(jiǎn)化的時(shí)序圖,這里省略了許多異步調(diào)用,忽略了多個(gè)不同的HTTP處理階段,僅標(biāo)識(shí)了在一個(gè)典型請(qǐng)求的處理過(guò)程中主要模塊被調(diào)用的流程,以此幫助讀者理解HTTP模塊如何處理用戶請(qǐng)求。完整的流程將在第11章中詳細(xì)介紹。從圖3-1中看到,worker進(jìn)程會(huì)在一個(gè)for循環(huán)語(yǔ)句里反復(fù)調(diào)用事件模塊檢測(cè)網(wǎng)絡(luò)事件。當(dāng)事件模塊檢測(cè)到某個(gè)客戶端發(fā)起的TCP請(qǐng)求時(shí)(接收到SY
12、N包),將會(huì)為它建立TCP連接,成功建立連接后根據(jù)nginx.conf文件中的配置會(huì)交由HTTP框架處理。HTTP框架會(huì)試圖接收完整的HTTP頭部,并在接收到完整的HTTP頭部后將請(qǐng)求分發(fā)到具體的HTTP模塊中處理。這種分發(fā)策略是多樣化的,其中最常見(jiàn)的是根據(jù)請(qǐng)求的URI和nginx.conf里location配置項(xiàng)的匹配度來(lái)決定如何分發(fā)(本章的例子正是應(yīng)用這種分發(fā)策略,在第10章中會(huì)介紹其他分發(fā)策略)。HTTP模塊在處理請(qǐng)求的結(jié)束時(shí),大多會(huì)向客戶端發(fā)送響應(yīng),此時(shí)會(huì)自動(dòng)地依次調(diào)用所有的HTTP過(guò)濾模塊,每個(gè)過(guò)濾模塊可以根據(jù)配置文件決定自己的行為。例如,gzip過(guò)濾模塊根據(jù)配置文件中的gzip o
13、n|off來(lái)決定是否壓縮響應(yīng)。HTTP處理模塊在返回時(shí)會(huì)將控制權(quán)交還給HTTP框架,如果在返回前設(shè)置了subrequest,那么HTTP框架還會(huì)繼續(xù)異步地調(diào)用適合的HTTP模塊處理子請(qǐng)求。開(kāi)發(fā)HTTP模塊時(shí),首先要注意的就是HTTP框架到具體的HTTP模塊間數(shù)據(jù)流的傳遞,以及開(kāi)發(fā)的HTTP模塊如何與諸多的過(guò)濾模塊協(xié)同工作(第10章、第11章會(huì)詳細(xì)介紹HTTP框架)。下面正式進(jìn)入HTTP模塊的開(kāi)發(fā)環(huán)節(jié)。 【責(zé)任編輯:b深入理解Nginx:模塊開(kāi)發(fā)與架構(gòu)解析第3章開(kāi)發(fā)一個(gè)簡(jiǎn)單的HTTP模塊,本章講述了如何開(kāi)發(fā)一個(gè)基本的HTTP模塊,這里除了獲取請(qǐng)求的包體外沒(méi)有涉及異步處理問(wèn)題。本節(jié)為大家
14、介紹定義自己的HTTP模塊。 3.4HTTP模塊的數(shù)據(jù)結(jié)構(gòu)(1)定義HTTP模塊方式很簡(jiǎn)單,例如:1. ngx_module_t ngx_http_mytest_module; 其中,ngx_module_t 是一個(gè)Nginx模塊的數(shù)據(jù)結(jié)構(gòu)(詳見(jiàn)8.2節(jié))。下面來(lái)分析一下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來(lái)定義,它已經(jīng)定義好了這7個(gè)值。 4. #define NGX_MODULE_V1 0, 0, 0, 0, 0, 0, 1 5. &
16、#160;6. 對(duì)于一類模塊(由下面的type成員決定類別)而言,ctx_index表示當(dāng)前模塊在這類模塊中的序號(hào)。這個(gè)成員常常是由管理這類模塊的一個(gè)Nginx核心模塊設(shè)置的,對(duì)于所有的HTTP模塊而言,ctx_index是由核心模塊ngx_http_module設(shè)置的。ctx_index非常重要,Nginx的模塊化設(shè)計(jì)非常依賴于各個(gè)模塊的順序,它們既用于表達(dá)優(yōu)先級(jí),也用于表明每個(gè)模塊的位置,借以幫助Nginx框架快速獲得某個(gè)模塊的數(shù)據(jù)(HTTP框架設(shè)置ctx_index的過(guò)程參見(jiàn)10.7節(jié))*/ 7.
17、60; ngx_uint_t ctx_index; 8. 9. /*index表示當(dāng)前模塊在ngx_modules數(shù)組中的序號(hào)。注意,ctx_index表示的是當(dāng)前模塊在一類模塊中的序號(hào),而index表示當(dāng)前模塊在所有模塊中的序號(hào),它同樣關(guān)鍵。Nginx啟動(dòng)時(shí)會(huì)根據(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; /模塊的版本,便于將來(lái)的擴(kuò)展。目前只有一種,默認(rèn)為1 23. ngx_uint_t version; 24. 25. /*ctx用于指向一類模塊的上下文結(jié)構(gòu)體,為什么需要ctx呢?因?yàn)榍懊嬲f(shuō)過(guò),Nginx模塊有許多種類,不同類模塊之間的功能差別很大。例如,事件類型的模塊主要處理I/O事件相關(guān)的功能,HT
22、TP類型的模塊主要處理HTTP應(yīng)用層的功能。這樣,每個(gè)模塊都有了自己的特性,而ctx將會(huì)指向特定類型模塊的公共接口。例如,在HTTP模塊中,ctx需要指向ngx_http_module_t結(jié)構(gòu)體*/ 26. void *ctx; 27. 28. /commands將
23、處理nginx.conf中的配置項(xiàng),詳見(jiàn)第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的啟動(dòng)、停止過(guò)程中,以下7個(gè)函數(shù)指針表示有7個(gè)執(zhí)行點(diǎn)會(huì)分別調(diào)用這7種方法(參見(jiàn)8.4節(jié)8.6節(jié))。對(duì)于任一個(gè)方法而言,如果不需要Nginx在某個(gè)時(shí)刻執(zhí)行它,那么簡(jiǎn)單地把它
25、設(shè)為NULL空指針即可*/ 35. 36. /*雖然從字面上理解應(yīng)當(dāng)在master進(jìn)程啟動(dòng)時(shí)回調(diào)init_master,但到目前為止,框架代碼從來(lái)不會(huì)調(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è)階段將在啟動(dòng)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)程的初始化過(guò)程會(huì)調(diào)用所有模塊的init_process函數(shù)*/ 41. ngx_int_t (*init_process)(ngx_cycle_t *cycle); 42. /* 由于Nginx暫不支持多線程模式,所以init_thread在框架代碼中沒(méi)有被調(diào)用過(guò),設(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)程會(huì)在退出前調(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、保留字段,目前沒(méi)有使用,但可用Nginx提供的NGX_MODULE_V1_PADDING宏來(lái)填充??匆幌略摵甑亩x:#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。對(duì)于下列回調(diào)方法:init_module、init_process、exit_process、exit_master,調(diào)用它們的是Nginx的框架代碼。換句話說(shuō),這4個(gè)回調(diào)方法與HTTP框架無(wú)關(guān),即使nginx.conf中沒(méi)有配置http .這種開(kāi)啟HTTP功能的配置項(xiàng),這些回調(diào)方法仍然會(huì)被調(diào)用。因此,通常開(kāi)發(fā)HTTP模塊時(shí)都把它們?cè)O(shè)為NULL空指針。這樣,當(dāng)Nginx不作為Web服務(wù)器使用時(shí),不會(huì)執(zhí)行HTTP模
36、塊的任何代碼。定義HTTP模塊時(shí),最重要的是要設(shè)置ctx和commands這兩個(gè)成員。對(duì)于HTTP類型的模塊來(lái)說(shuō),ngx_module_t中的ctx指針必須指向ngx_http_module_t接口(HTTP框架的要求)。下面先來(lái)分析ngx_http_module_t結(jié)構(gòu)體的成員。 3.4HTTP模塊的數(shù)據(jù)結(jié)構(gòu)(2)HTTP框架在讀取、重載配置文件時(shí)定義了由ngx_http_module_t接口描述的8個(gè)階段,HTTP框架在啟動(dòng)過(guò)程中會(huì)在每個(gè)階段中調(diào)用ngx_http_module_t中相應(yīng)的方法。當(dāng)然,如果ngx_http_module_t中的某個(gè)回調(diào)方法設(shè)為NULL空指針,那么H
37、TTP框架是不會(huì)調(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)用于存儲(chǔ)main級(jí)別(直屬于http.塊的配置項(xiàng))的全局配置項(xiàng)時(shí),可以通過(guò)create_main_conf回調(diào)方法創(chuàng)建存儲(chǔ)全局配置項(xiàng)的結(jié)構(gòu)體*/ 8. void *(*create_main_conf)(ngx_conf_t *cf); 9.
39、 /常用于初始化main級(jí)別配置項(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)用于存儲(chǔ)srv級(jí)別(直屬于虛擬主機(jī)server.塊的配置項(xiàng))的配置項(xiàng)時(shí),可以通過(guò)實(shí)現(xiàn)create_srv_conf回調(diào)方
40、法創(chuàng)建存儲(chǔ)srv級(jí)別配置項(xiàng)的結(jié)構(gòu)體*/ 13. void *(*create_srv_conf)(ngx_conf_t *cf); 14. / merge_srv_conf回調(diào)方法主要用于合并main級(jí)別和srv級(jí)別下的同名配置項(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)用于存儲(chǔ)loc級(jí)別(直屬于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級(jí)別和loc級(jí)別下的同名配置項(xiàng) 20. char *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf); 21. ngx_ht
43、tp_module_t; 不過(guò),這8個(gè)階段的調(diào)用順序與上述定義的順序是不同的。在Nginx啟動(dòng)過(guò)程中,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í)首先會(huì)遍歷所有的模塊,對(duì)于每一個(gè)模塊而言,即通過(guò)遍歷commands數(shù)組進(jìn)行,另外,在數(shù)組中檢查到ngx_null_command時(shí),會(huì)停止使用當(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)后,將會(huì)調(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)在什么樣的場(chǎng)景下開(kāi)始處理用戶請(qǐng)求,也就是說(shuō),先要弄清楚我們的模塊是如何介入到Nginx處理用戶請(qǐng)求的流程中的。從2.4節(jié)中的HTTP配置項(xiàng)意義可知,一個(gè)HTTP請(qǐng)求會(huì)被許多個(gè)配置項(xiàng)控制,實(shí)際上這是因?yàn)橐粋€(gè)HTTP請(qǐng)求可以被許多個(gè)HTTP模塊同時(shí)處理。這樣一來(lái),肯定會(huì)有一個(gè)先后問(wèn)題,也就是說(shuō),誰(shuí)先處理請(qǐng)求誰(shuí)的“權(quán)力”就更大。例如,ngx_http_access_module模塊的deny選項(xiàng)一旦得到滿足后,Nginx就會(huì)決定拒絕來(lái)自某個(gè)IP的請(qǐng)求,后面的諸如root這種訪問(wèn)靜態(tài)文件的處理方式是得不到執(zhí)行的。另外,由于同一個(gè)配置
51、項(xiàng)可以從屬于許多個(gè)server、location配置塊,那么這個(gè)配置項(xiàng)將會(huì)針對(duì)不同的請(qǐng)求起作用。因此,現(xiàn)在面臨的問(wèn)題是,我們希望自己的模塊在哪個(gè)時(shí)刻開(kāi)始處理請(qǐng)求?是希望自己的模塊對(duì)到達(dá)Nginx的所有請(qǐng)求都起作用,還是希望只對(duì)某一類請(qǐng)求(如URI匹配了location后表達(dá)式的請(qǐng)求)起作用?Nginx的HTTP框架定義了非常多的用法,我們有很大的自由來(lái)定義自己的模塊如何介入HTTP請(qǐng)求的處理,但本章只想說(shuō)明最簡(jiǎn)單、最常見(jiàn)的HTTP模塊應(yīng)當(dāng)如何編寫,因此,我們這樣定義第一個(gè)HTTP模塊介入Nginx的方式:1)不希望模塊對(duì)所有的HTTP請(qǐng)求起作用。2)在nginx.conf文件中的http、se
52、rver或者location塊內(nèi)定義mytest配置項(xiàng),如果一個(gè)用戶請(qǐng)求通過(guò)主機(jī)域名、URI等匹配上了相應(yīng)的配置塊,而這個(gè)配置塊下又具有mytest配置項(xiàng),那么希望mytest模塊開(kāi)始處理請(qǐng)求。在這種介入方式下,模塊處理請(qǐng)求的順序是固定的,即必須在HTTP框架定義的NGX_HTTP_CONTENT_PHASE階段開(kāi)始處理請(qǐng)求,具體內(nèi)容下文詳述。下面開(kāi)始按照這種方式定義mytest模塊。首先,定義mytest配置項(xiàng)的處理。從上文中關(guān)于ngx_command_t結(jié)構(gòu)的說(shuō)明來(lái)看,只需要定義一個(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將會(huì)調(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級(jí)別配置項(xiàng),也就是說(shuō),在每個(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框架在處理用戶請(qǐng)求進(jìn)行到NGX_HTTP_CONTENT_PHASE階段時(shí),如果請(qǐng)求的主機(jī)域名、URI與mytest配置項(xiàng)所在的配置塊相匹配,就將調(diào)用我們實(shí)現(xiàn)的ngx_http_mytest_handler方法處理這個(gè)請(qǐng)求*/ 10. clcf->handler =
58、;ngx_http_mytest_handler; 11. 12. return NGX_CONF_OK; 13. 當(dāng)Nginx接收完HTTP請(qǐng)求的頭部信息時(shí),就會(huì)調(diào)用HTTP框架處理請(qǐng)求,另外在11.6節(jié)描述的NGX_HTTP_CONTENT_PHASE階段將有可能調(diào)用mytest模塊處理請(qǐng)求。在ngx_http_mytest方法中,我們定義了請(qǐng)求的處理方法為ngx_http_mytest_handler,舉個(gè)例子來(lái)說(shuō),如果用戶的請(qǐng)求URI是/test/example,而在配置文件中有這
59、樣的location塊: 1. Location /test 2. mytest; 3. 那么,HTTP框架在NGX_HTTP_CONTENT_PHASE階段就會(huì)調(diào)用到我們實(shí)現(xiàn)的ngx_http_mytest_handler方法來(lái)處理這個(gè)用戶請(qǐng)求。事實(shí)上,HTTP框架共定義了11個(gè)階段(第三方HTTP模塊只能介入其中的7個(gè)階段處理請(qǐng)求,詳見(jiàn)10.6節(jié)),本章只關(guān)注NGX_HTTP_CONTENT_PHASE處理階段,多數(shù)HTTP模塊都在此階段實(shí)現(xiàn)相關(guān)功能。下面簡(jiǎn)單說(shuō)明一下這11個(gè)
60、階段。1. typedef enum 2. /在接收到完整的HTTP頭部后處理的HTTP階段 3. NGX_HTTP_POST_READ_PHASE = 0, 4. 5. /*在還沒(méi)有查詢到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)檫@兩者會(huì)導(dǎo)致查找到不同的location塊(location是與URI進(jìn)行匹配的)*/ 12. NGX_HTTP_REWRITE_PHASE, 13. 14. /*這一階段是用于在rewrite重寫URL后重新跳到NGX_HTTP_FIND_CONFIG_PHASE階段,找到與新的URI匹配的location。所以,這一階段是無(wú)法由第三方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è)請(qǐng)求訪問(wèn)Nginx服務(wù)器
64、60;21. NGX_HTTP_ACCESS_PHASE, 22. 23. /*當(dāng)NGX_HTTP_ACCESS_PHASE階段中HTTP模塊的handler處理方法返回不允許訪問(wèn)的錯(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請(qǐng)求訪問(wèn)靜態(tài)文件資源時(shí),try_files配置項(xiàng)可以使這個(gè)請(qǐng)求順序地訪問(wèn)多個(gè)靜態(tài)文件資源,如果某一次訪問(wèn)失敗,則繼續(xù)訪問(wèn)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請(qǐng)求內(nèi)容的階段,這是大部分HTTP模塊最喜歡介入的階段 30. NGX_HTTP_CONTENT_PHASE, 31. 32. /*處理完請(qǐng)求后記錄日志的階段。例如,ngx_http_log_module模塊就在這個(gè)階段中加入了一個(gè)handler處理方法,使得每個(gè)HTTP請(qǐng)求處理完畢后會(huì)記錄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)處理請(qǐng)求的ngx_http_mytest_handler方法,如果沒(méi)有什么工作是必須在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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 創(chuàng)新管理與組織變革-洞察闡釋
- 樂(lè)理卷子試題及答案
- 胎盤黃疸與新生兒黃疸的遺傳易感性研究-洞察闡釋
- 業(yè)務(wù)合同執(zhí)行狀態(tài)跟蹤統(tǒng)計(jì)表
- 線上線下游戲融合-洞察闡釋
- 2025大學(xué)食堂餐飲承包合同
- 煙草種植現(xiàn)場(chǎng)調(diào)研與質(zhì)量控制合同范本
- 保密項(xiàng)目參觀保密協(xié)議書模板
- 車輛抵押貸款風(fēng)險(xiǎn)分析合同模板
- 柴油儲(chǔ)備庫(kù)建設(shè)與購(gòu)銷合作協(xié)議
- DBJ51 014-2021 四川省建筑地基基礎(chǔ)檢測(cè)技術(shù)規(guī)程
- PCB 設(shè)計(jì)技巧
- 消防施工測(cè)量記錄(建筑分類)
- 八年級(jí)初二物理上冊(cè)期末試卷及答案(人教版)
- 部編版六年級(jí)下冊(cè)道德與法治知識(shí)點(diǎn)大匯總
- 汽車維修技術(shù)論文兩篇
- 心理學(xué)基礎(chǔ)試卷A
- 電動(dòng)車使用維修指南
- 中國(guó)民航管理干部學(xué)院新生報(bào)名登記表
- 城市主干道工程監(jiān)理大綱
- 《2021國(guó)標(biāo)暖通圖集資料》14K117-3 錐形風(fēng)帽
評(píng)論
0/150
提交評(píng)論