手把手教你開發(fā)Nginx模塊_第1頁
手把手教你開發(fā)Nginx模塊_第2頁
手把手教你開發(fā)Nginx模塊_第3頁
手把手教你開發(fā)Nginx模塊_第4頁
手把手教你開發(fā)Nginx模塊_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、手把手教你開發(fā)Nginx模塊前面的哪些話關(guān)于Nginx模塊開發(fā)的博客資料,網(wǎng)上很多,很多。但是,每篇博客都只提要點,無法"step by step"照著做,對于初次接觸Nginx開發(fā)的同學(xué),只能像只盲目的螞蟻瞎燥急!該篇文章沒有太多技術(shù)深度,只是一步一步說明白Nginx模塊的開發(fā)過程。開發(fā)環(huán)境搭建工欲善其事,必先利其器。個人推薦Eclipse CDT 作為IDE,原因很簡單,代碼提示與補全功能很全,完勝Codeblock這類.相信與否,試過就知道。在ubuntu下搭建開發(fā)環(huán)境:安裝GCC編譯器apt-get install build-essential安裝pcre/ope

2、nssl/zlib開發(fā)庫apt-get install libpcre3-devapt-get install libssl-devapt-get install libzip-dev必需安裝nginx核心模塊依賴的pcre,openssl,zilib開發(fā)庫安裝JRE/Eclipse CDTapt-get install openjdk-8-jrewget http:/ftp.yz.yamagata-u.ac.jp/pub/eclipse/technology/epp/downloads/release/neon/R/eclipse-cpp-neon-R-linux-gtk-x86_64.ta

3、r.gz && tzr -xzvf eclipse-cpp-neon-R-linux-gtk-x86_64.tar.gz下載nginx源碼wget /download/nginx-1.10.1.tar.gz && tar -xzvf nginx-1.10.1.tar.gz配置CDT Build Environment添加變量,值Nginx src下各模塊路徑,用冒號分隔,例如:/root/Workspace/nginx-1.10.1/src/core:/root/Workspace/nginx-1.10.1/src/event:/r

4、oot/Workspace/nginx-1.10.1/src/http:/root/Workspace/nginx-1.10.1/src/mail:/root/Workspace/nginx-1.10.1/src/stream:/root/Workspace/nginx-1.10.1/src/os/unix 添加環(huán)境變量,創(chuàng)建C項目時自動作為-I選項imageimageNginx模塊編譯流程Nginx使用configure腳本分析環(huán)境,自動生成objs結(jié)果。哪么configure如何編譯第三方模塊?答案是-add-module指定第三方模塊目錄,并將目錄存為$ngx_addon_dir環(huán)境變量

5、。執(zhí)行$ngx_addon_dir/config腳本,讀取模塊配置。在config中的環(huán)境變量分為2種:小寫的本地環(huán)境變量,大寫的全局環(huán)境變量。例如:ngx_addon_name=ngx_http_mytest_moduleHTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module" NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_moudle.c"CORE_LIBS="$CORE_LIBS -lpcre"HTTP_

6、MODULES中的ngx_http_mytest_module就是NGX_ADDON_SRCS中源碼(如果有多個,都要寫上)ngx_http_mytest_module.c中定義的ngx_module_t類型的全局變量。可見,第三方模塊的入口點就是ngx_module_t類型全局變量,該變量又關(guān)聯(lián)ngx_http_module_t類型static變量,與ngx_command_t類型static數(shù)組。在ngx_http_module_t中定義上下文配置nginx.conf解析的回調(diào)方法。在ngx_command_t中定義配置項處理的set回調(diào)方法。Nginx的全部操作都是異步的。在上述的方法中

7、根據(jù)需要又會使用其他handler方法。以上可以看成Nginx第三方模塊的起式。Upstream例子源碼configngx_addon_name=ngx_http_mytest_moduleHTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module"NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_module.c"源代碼#include <ngx_config.h>#include <ngx_core.h>#in

8、clude <ngx_http.h>#include <ngx_stream.h>typedef struct ngx_http_upstream_conf_t upstream; mytest_conf_t;typedef struct ngx_http_status_t status; ngx_str_t backendServer; mytest_ctx_t;static void *mytest_create_loc_conf(ngx_conf_t *cf);static char *mytest_merge_loc_conf(ngx_conf_t *cf, v

9、oid *parent, void *child);static ngx_int_t mytest_upstream_create_request(ngx_http_request_t *r);static ngx_int_t mytest_upstream_process_status_line(ngx_http_request_t *r);static ngx_int_t mytest_upstream_process_header(ngx_http_request_t *r);static void mytest_upstream_finalize_request(ngx_http_re

10、quest_t *r, ngx_int_t rc);static ngx_int_t mytest_handler(ngx_http_request_t *r);static char *mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static ngx_http_module_t mytest_ctx = NULL, NULL, NULL, NULL, NULL, NULL, mytest_create_loc_conf, mytest_merge_loc_conf;static ngx_command_t mytest_com

11、mands = ngx_string("mytest"), NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_NOARGS, mytest, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL , ngx_null_command;ngx_module_t ngx_http_mytest_module = NGX_MODULE_V1, &mytest_ctx, mytest_commands, NGX_HTTP_MODUL

12、E, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NGX_MODULE_V1_PADDING;static ngx_str_t mytest_upstream_hide_headers = ngx_string("Date"), ngx_string("Server"), ngx_string("X-Pad"), ngx_string("X-Accel-Expires"), ngx_string("X-Accel-Redirect"), ngx_strin

13、g("X-Accel-Limit-Rate"), ngx_string("X-Accel-Buffering"), ngx_string("X-Accel-Charset"), ngx_null_string;static void *mytest_create_loc_conf(ngx_conf_t *cf) mytest_conf_t *mycf; mycf = (mytest_conf_t *)ngx_pcalloc(cf->pool, sizeof(mytest_conf_t); if(mycf = NULL) retu

14、rn NULL; mycf->upstream.connect_timeout = 60000; mycf->upstream.send_timeout = 60000; mycf->upstream.read_timeout = 60000; mycf->upstream.store_access = 0600; mycf->upstream.buffering = 0; mycf->upstream.bufs.num = 8; mycf->upstream.bufs.size = ngx_pagesize; mycf->upstream.bu

15、ffer_size = ngx_pagesize; mycf->upstream.busy_buffers_size = 2 * ngx_pagesize; mycf->upstream.temp_file_write_size = 2 * ngx_pagesize; mycf->upstream.max_temp_file_size = 1024 * 1024 *1024; mycf->upstream.hide_headers = NGX_CONF_UNSET_PTR; mycf->upstream.pass_headers = NGX_CONF_UNSET_

16、PTR; return mycf;static char *mytest_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) mytest_conf_t *prev = (mytest_conf_t *)parent; mytest_conf_t *conf = (mytest_conf_t *)child; ngx_hash_init_t hash; hash.max_size = 100; hash.bucket_size = 1024; = "proxy_headers_hash" i

17、f(ngx_http_upstream_hide_headers_hash(cf,&conf->upstream, &prev->upstream,mytest_upstream_hide_headers,&hash)!=NGX_OK) return NGX_CONF_ERROR; return NGX_CONF_OK;static ngx_int_t mytest_upstream_create_request(ngx_http_request_t *r) static ngx_str_t backendQueryLine = ngx_string(&qu

18、ot;GET /search?q=%V HTTP/1.1rnHost: .hkrnConnection: closernrn"); ngx_int_t queryLineLen = backendQueryLine.len + r->args.len - 2; ngx_buf_t *b = ngx_create_temp_buf(r->pool, queryLineLen); if(b = NULL) return NGX_ERROR; b->last = b->pos + queryLineLen; ngx_snprintf(b->pos, query

19、LineLen, (char *)backendQueryLine.data, &r->args); r->upstream->request_bufs = ngx_alloc_chain_link(r->pool); if(r->upstream->request_bufs = NULL) return NGX_ERROR; r->upstream->request_bufs->buf = b; r->upstream->request_bufs->next = NULL; r->upstream->

20、request_sent = 0; r->upstream->header_sent = 0; r->header_hash = 1; return NGX_OK;static ngx_int_t mytest_upstream_process_status_line(ngx_http_request_t *r) size_t len; ngx_int_t rc; ngx_http_upstream_t *u; mytest_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module); if(ctx = NU

21、LL) return NGX_ERROR; u = r->upstream; rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status); if(rc = NGX_AGAIN) return rc; if(rc = NGX_ERROR) ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent to valid HTTP/1.0 header"); r->http_version = NGX

22、_HTTP_VERSION_9; u->state->status = NGX_HTTP_OK; return NGX_OK; if(u->state) u->state->status = ctx->status.code; u->headers_in.status_n = ctx->status.code; len = ctx->status.end - ctx->status.start; u->headers_in.status_line.len = len; u->headers_in.status_line.d

23、ata = ngx_pcalloc(r->pool, len); if(u->headers_in.status_line.data = NULL) return NGX_ERROR; ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len); u->process_header = mytest_upstream_process_header; return mytest_upstream_process_header(r);static ngx_int_t mytest_upstrea

24、m_process_header(ngx_http_request_t *r) ngx_int_t rc; ngx_table_elt_t *h; ngx_http_upstream_header_t *hh; ngx_http_upstream_main_conf_t *umcf; umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); for(;) rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1); if(rc = NGX_

25、OK) h = ngx_list_push(&r->upstream->headers_in.headers); if(h = NULL) return NGX_ERROR; h->hash = r->header_hash; h->key.len = r->header_name_end - r->header_name_start; h->value.len = r->header_end - r->header_start; h->key.data = ngx_pcalloc(r->pool, h->k

26、ey.len + 1 + h->value.len + 1 + h->key.len); if(h->key.data = NULL) return NGX_ERROR; h->value.data = h->key.data + h->key.len + 1; h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; ngx_memcpy(h->key.data, r->header_name_start, h->key.len); h-&g

27、t;key.datah->key.len='0' ngx_memcpy(h->value.data, r->header_start, h->value.len); h->value.datah->value.len = '0' if(h->key.len = r->lowcase_index) ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); else ngx_strlow(h->lowcase_key, h->ke

28、y.data, h->key.len); hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len); if(hh && hh->handler(r, h, hh->offset)!=NGX_OK) return NGX_ERROR; continue; if(rc = NGX_HTTP_PARSE_HEADER_DONE) if(r->upstream->headers_in.server = NULL) h = n

29、gx_list_push(&r->upstream->headers_in.headers); if(h = NULL) return NGX_ERROR; h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r'); ngx_str_set(&h->key, "Server"); ngx_str_null(&h-&

30、gt;value); h->lowcase_key = (u_char *)"server" if(r->upstream->headers_in.date = NULL) h = ngx_list_push(&r->upstream->headers_in.headers); if(h = NULL) return NGX_ERROR; h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e'); ngx_s

31、tr_set(&h->key, "Date"); ngx_str_null(&h->value); h->lowcase_key = (u_char *)"date" return NGX_OK; if(rc = NGX_AGAIN) return NGX_AGAIN; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent invalid header"); return NGX_HTTP_UPSTREAM_FT_

32、INVALID_HEADER; static void mytest_upstream_finalize_request(ngx_http_request_t *r, ngx_int_t rc) ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "mytest_upstream_finalize_request");static char *mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_http_core_loc_conf_t *clcf

33、; clcf = ngx_http_conf_get_module_loc_conf(cf,ngx_http_core_module); clcf->handler = mytest_handler; return NGX_CONF_OK;static ngx_int_t mytest_handler(ngx_http_request_t *r) mytest_ctx_t *myctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module); if(myctx = NULL) myctx = ngx_pcalloc(r->pool,

34、 sizeof(mytest_ctx_t); if(myctx = NULL) return NGX_ERROR; ngx_http_set_ctx(r, myctx, ngx_http_mytest_module); if(ngx_http_upstream_create(r)!=NGX_OK) ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_upstream_create() failed"); return NGX_ERROR; mytest_conf_t *mycf = (mytes

35、t_conf_t *)ngx_http_get_module_loc_conf(r, ngx_http_mytest_module); ngx_http_upstream_t *u = r->upstream; u->conf = &mycf->upstream; u->buffering = mycf->upstream.buffering; u->resolved = (ngx_http_upstream_resolved_t *) ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved

36、_t); if(u->resolved = NULL) ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_pcalloc resolved error. %s", strerror(errno); return NGX_ERROR; static struct sockaddr_in backendSockAddr; struct hostent *pHost = gethostbyname(char *)".hk"); if(pHost = NULL) ngx_log_err

37、or(NGX_LOG_ERR, r->connection->log, 0, "gethostbyname fail. %s", strerror(errno); return NGX_ERROR; backendSockAddr.sin_family = AF_INET; backendSockAddr.sin_port = htons(in_port_t)80); char *pDmsIP = inet_ntoa(*(struct in_addr *)(pHost->h_addr_list0); backendSockAddr.sin_addr.s_a

38、ddr = inet_addr(pDmsIP); myctx->backendServer.data = (u_char *)pDmsIP; myctx->backendServer.len = strlen(pDmsIP); u->resolved->sockaddr = (struct sockaddr *)&backendSockAddr; u->resolved->port = htons(in_port_t)80); u->resolved->socklen = sizeof(struct sockaddr_in); u->

39、;resolved->naddrs = 1; u->create_request = mytest_upstream_create_request; u->process_header = mytest_upstream_process_status_line; u->finalize_request = mytest_upstream_finalize_request; r->main->count+; ngx_http_upstream_init(r); return NGX_DONE;注意:Nginx深入解析的demo少了這句:“u->resol

40、ved->port = htons(in_port_t)80);”,否則報錯“2016/09/09 11:24:18 error 28352#0: *1 no port in upstream "", client: , server: localhost, request: "GET /mytest?q=test HTTP/1.1", host: "localhost"”編譯腳本./configure -prefix=/usr/local/nginx -add-module=/root/Workspace/n

41、ginx-modules/ngx_http_mytest_module -with-debugsudo makesudo make install安裝后即可到/usr/local/nginx下配置nginx.conf進行測試。Subrequest例子源碼configngx_addon_name=ngx_http_mytest_moduleHTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module"NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_m

42、odule.c"源代碼#include <ngx_config.h>#include <ngx_core.h>#include <ngx_http.h>typedef struct ngx_str_t stock6; mytest_ctx_t;static ngx_int_t mytest_subrequest_post_handler(ngx_http_request_t *r, void *data, ngx_int_t rc);static void mytest_post_handler(ngx_http_request_t *r);sta

43、tic ngx_int_t mytest_handler(ngx_http_request_t *r);static char *mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static ngx_http_module_t mytest_conf = NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL;static ngx_command_t mytest_commands = ngx_string("mytest"), NGX_HTTP_MAIN_CONF | NG

44、X_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS, mytest, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL , ngx_null_command;ngx_module_t ngx_http_mytest_module = NGX_MODULE_V1, &mytest_conf, mytest_commands, NGX_HTTP_MODULE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NGX_MODULE_V1_PADDING;static ngx_int_

45、t mytest_subrequest_post_handler(ngx_http_request_t *r, void *data, ngx_int_t rc) ngx_http_request_t *pr = r->parent; mytest_ctx_t *myctx = ngx_http_get_module_ctx(pr, ngx_http_mytest_module); pr->headers_out.status = r->headers_out.status; if (r->headers_out.status = NGX_HTTP_OK) int fl

46、ag = 0; ngx_buf_t *pRecvBuf = &r->upstream->buffer; for (; pRecvBuf->pos != pRecvBuf->last; pRecvBuf->pos+) if (*pRecvBuf->pos = ',' | *pRecvBuf->pos = '"') if (flag > 0) myctx->stockflag - 1.len = pRecvBuf->pos - myctx->stockflag - 1.data; f

47、lag+; myctx->stockflag - 1.data = pRecvBuf->pos + 1; if (flag > 6) break; pr->write_event_handler = mytest_post_handler; return NGX_OK;static void mytest_post_handler(ngx_http_request_t *r) if(r->headers_out.status != NGX_HTTP_OK) ngx_http_finalize_request(r,r->headers_out.status);

48、 return; mytest_ctx_t *myctx = ngx_http_get_module_ctx(r,ngx_http_mytest_module); ngx_str_t output_format = ngx_string("stock%V,Today current price:%V, volumn:%V"); int bodylen = output_format.len + myctx->stock0.len + myctx->stock1.len + myctx->stock4.len - 6; r->headers_out.c

49、ontent_length_n = bodylen; ngx_buf_t *b = ngx_create_temp_buf(r->pool, bodylen); ngx_snprintf(b->pos,bodylen,(char *)output_format.data, &myctx->stock0, &myctx->stock1, &myctx->stock4); b->last = b->pos + bodylen; b->last_buf = 1; ngx_chain_t out; out.buf = b; out.next = NULL; static ngx_str_t type = ngx_string(

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論