解剖Nginx·模組開發篇(1)跑起你的 Hello World 模組!
解剖Nginx·模組開發篇(1)跑起你的 Hello World 模組!
- 作者:柳大·Poechant(鍾超)
- 郵箱:zhongchao.ustc#gmail.com(# -> @)
- 部落格:Blog.CSDN.net/Poechant
- 日期:June 2nd, 2012
1 學習 Nginx 模組開發需要有哪些準備?
需要的預備知識不多,有如下幾點:
- 有過一些 C 語言的程式設計經歷;
- 知道 Nginx 是幹嘛的,並有過編寫或改寫 Nginx 的配置檔案的經歷。
OK,就這兩點就夠了 :)
好了,那就開始吧~
2 我們的 HelloWorld 的目標是什麼?
我們的目標,就是你在瀏覽器裡輸入http://localhost/hello_world
時,顯示:
hello world
當然,為了能夠更加自定義一些,我們嘗試在hello world
後面再顯示一個字串,比如:
hello world, Poechant
那麼我們的配置檔案看起來是什麼樣的呢?
http {
include mime.types;
default_type application/octet-stream;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.php index.html index.htm;
}
location /hello_world {
hello_world Poechant;
}
}
}
是的,很簡單吧,唯一特別的部分,就是:
location /hello_world {
hello_world Poechant;
}
3 開工
3.1 目錄結構
首先要明確,我們的檔案和目錄結構:
ngx_http_hello_world_module
|_____________ngx_http_hello_world_module.c
|_____________config
其中ngx_http_hello_world_module.c
是模組的 C 原始碼檔案,config
是模組的配置檔案。
3.2 ngx_http_hello_world_module.c
定義一個結構體:
typedef struct {
ngx_str_t output_words;
} ngx_http_hello_world_loc_conf_t;
定義三個變數:
// Structure for the HelloWorld command
static ngx_command_t ngx_http_hello_world_commands[] = {
{
ngx_string("hello_world"), // The command name
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_http_hello_world, // The command handler
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_hello_world_loc_conf_t, output_words),
NULL
},
ngx_null_command
};
// Structure for the HelloWorld context
static ngx_http_module_t ngx_http_hello_world_module_ctx = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
ngx_http_hello_world_create_loc_conf,
ngx_http_hello_world_merge_loc_conf
};
// Structure for the HelloWorld module, the most important thing
ngx_module_t ngx_http_hello_world_module = {
NGX_MODULE_V1,
&ngx_http_hello_world_module_ctx,
ngx_http_hello_world_commands,
NGX_HTTP_MODULE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NGX_MODULE_V1_PADDING
};
定義三個函式:
static char* ngx_http_hello_world(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
static void* ngx_http_hello_world_create_loc_conf(ngx_conf_t* cf)
static char* ngx_http_hello_world_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child)
完整的程式如下:
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
typedef struct {
ngx_str_t output_words;
} ngx_http_hello_world_loc_conf_t;
// To process HelloWorld command arguments
static char* ngx_http_hello_world(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
// Allocate memory for HelloWorld command
static void* ngx_http_hello_world_create_loc_conf(ngx_conf_t* cf);
// Copy HelloWorld argument to another place
static char* ngx_http_hello_world_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child);
// Structure for the HelloWorld command
static ngx_command_t ngx_http_hello_world_commands[] = {
{
ngx_string("hello_world"), // The command name
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_http_hello_world, // The command handler
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_hello_world_loc_conf_t, output_words),
NULL
},
ngx_null_command
};
// Structure for the HelloWorld context
static ngx_http_module_t ngx_http_hello_world_module_ctx = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
ngx_http_hello_world_create_loc_conf,
ngx_http_hello_world_merge_loc_conf
};
// Structure for the HelloWorld module, the most important thing
ngx_module_t ngx_http_hello_world_module = {
NGX_MODULE_V1,
&ngx_http_hello_world_module_ctx,
ngx_http_hello_world_commands,
NGX_HTTP_MODULE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NGX_MODULE_V1_PADDING
};
static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t* r) {
ngx_int_t rc;
ngx_buf_t* b;
ngx_chain_t out[2];
ngx_http_hello_world_loc_conf_t* hlcf;
hlcf = ngx_http_get_module_loc_conf(r, ngx_http_hello_world_module);
r->headers_out.content_type.len = sizeof("text/plain") - 1;
r->headers_out.content_type.data = (u_char*)"text/plain";
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
out[0].buf = b;
out[0].next = &out[1];
b->pos = (u_char*)"hello_world, ";
b->last = b->pos + sizeof("hello_world, ") - 1;
b->memory = 1;
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
out[1].buf = b;
out[1].next = NULL;
b->pos = hlcf->output_words.data;
b->last = hlcf->output_words.data + (hlcf->output_words.len);
b->memory = 1;
b->last_buf = 1;
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = hlcf->output_words.len + sizeof("hello_world, ") - 1;
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
return rc;
}
return ngx_http_output_filter(r, &out[0]);
}
static void* ngx_http_hello_world_create_loc_conf(ngx_conf_t* cf) {
ngx_http_hello_world_loc_conf_t* conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_hello_world_loc_conf_t));
if (conf == NULL) {
return NGX_CONF_ERROR;
}
conf->output_words.len = 0;
conf->output_words.data = NULL;
return conf;
}
static char* ngx_http_hello_world_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child) {
ngx_http_hello_world_loc_conf_t* prev = parent;
ngx_http_hello_world_loc_conf_t* conf = child;
ngx_conf_merge_str_value(conf->output_words, prev->output_words, "Nginx");
return NGX_CONF_OK;
}
static char* ngx_http_hello_world(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) {
ngx_http_core_loc_conf_t* clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_hello_world_handler;
ngx_conf_set_str_slot(cf, cmd, conf);
return NGX_CONF_OK;
}
3.3 config
ngx_addon_name=ngx_http_hello_world_module
HTTP_MODULES="$HTTP_MODULES ngx_http_hello_world_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_world_module.c"
3.4 編寫配置檔案
最開始已經展示過了,就是它。
3.5 編譯你的模組
$ ./configure --add-module=/your/module/path/ngx_http_hello_world_module
make
如果沒有任何錯誤提示的話,那麼恭喜你,你的模組編譯通過了!
然後執行 Nginx。如果沒有任何錯誤提示的話,再次恭喜你,你的模組已經被正常載入執行了!
3.6 測試你的模組
http://localhost/hello_world
你應該會看到:
hello_world, Poechant
這個簡單模組的詳細解釋,在該系列博文的第二、三、四篇中。
4 恐怕我還是要說一些“非程式碼”
一般來說,剛入門做某件事情的時候,我們不大想聽廢話,希望趕緊開始上手幹活,否則會覺得很空洞。這也是為什麼我一開始就上了一個例子,並給出程式碼。但是還是要了解一些“空話”,才有助於理解。
Nginx 處理請求的過程,是在請求收到後定位到配置檔案中描述的相應 location,然後由 handler 生成 response,再由 filter 進行處理。所以模組開發,可以是 handler 模組開發,也可以是 filter 模組開發(當然還有其他型別的模組)。
5 推薦一些參考
- Emiller’s Guide to Nginx Module Development
- Emiller’s Advanced Topics in Nginx Module Development
- crk_world的部落格
- Ngx Deve Kit
- Emiller’s Guide To Nginx Module Development 中文版
- Nginx & OpenResty
- CodingLabs-Nginx模組開發入門
-
轉載請註明來自柳大的CSDN部落格:Blog.CSDN.net/Poechant
-
相關文章
- 解剖Nginx·模組開發篇(2)ngx_http_hello_world_module 模組基本結構定義NginxHTTP
- 解剖Nginx·模組開發篇(3)ngx_http_hello_world_module 模組的基本函式實現NginxHTTP函式
- 解剖Nginx·模組開發篇(4)模組開發中的命名規則和模組載入與執行流程Nginx
- 解剖Nginx·模組開發篇(6)配置檔案config入門Nginx
- 解剖Nginx·模組開發篇(5)解讀內建非預設模組 ngx_http_stub_status_moduleNginxHTTP
- nginx 編寫簡單HTTP模組以及nginx http handler的hello world示例編寫NginxHTTP
- nginx模組開發Nginx
- rust入門篇-hello worldRust
- nginx事件模組 -- 第二篇Nginx事件
- nginx事件模組-- 第四篇Nginx事件
- nginx事件模組 -- 第三篇Nginx事件
- Nginx的Uwsgi模組(部分模組指令)Nginx
- hello world"你知多少------300種程式語言中的"hello world"程式匯
- nginx事件模組 -- 第一篇Nginx事件
- Nginx常用的模組Nginx
- Nginx的Uwsgi模組Nginx
- Andorid Studio NDK開發-Hello World
- Andorid Studio NDK 開發 - Hello World
- Andorid Studio NDK開發:Hello World
- Python基礎1 Hello World!Python
- [第七篇]——Docker Hello WorldDocker
- NGINX模組(一)Nginx
- NGINX模組(二)Nginx
- Hello World
- Nginx limit模組限制併發數NginxMIT
- 一篇文章說透Nginx的rewrite模組Nginx
- Xposed模組的開發
- C++ COM 開發 Hello World V2C++
- Jbpm3.2 開發一個Hello World程式
- react的”Hello World !“React
- WebGL 的 Hello WorldWeb
- nginx事件模組 -- 第五篇 epoll addNginx事件
- 學習Scala第一篇-從hello World開始
- Nginx 新增 lua 模組Nginx
- 為 Nginx 新增模組Nginx
- React Native——搭建開發環境、建立Hello WorldReact Native開發環境
- 使用typescript開發angular模組(編寫模組)TypeScriptAngular
- Go - Hello WorldGo