第三章 編寫Hello world模塊
-
在nginx源代碼根目錄下創建文件夾plugin
humeng@humeng-virtual-machine:~/nginx-1.14.2/src$ mkdir plugin
- 編寫config文件
創建hello.config配置文件,並進行編輯
humeng@humeng-virtual-machine:~/nginx-1.14.2/src/plugin$ sudo touch config
humeng@humeng-virtual-machine:~/nginx-1.14.2/src/plugin$ sudo gedit config
hello.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"
ngx_addon_name:要開發的模塊名稱
HTTP_MODULES:將我們的模塊名稱添加到HTTP_MODULES變量中
NGX_ADDON_SRCS:表示新增模塊的源代碼路徑
- 編寫模塊文件
創建ngx_http_hello_world_module.c文件,編寫hello world程序運行需要的各個模塊,具體代碼如下:
#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;
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);
static ngx_command_t ngx_http_hello_world_commands[] =
{ //commands結構體,設定配置項特定的處理方式,定義該處理項出現時的處理函數
{
//配置項的名字
ngx_string("hello_world"),
//NGX_HTTP_LOC_CONF表示指令在位置配置部分出現是合法的 ,NGX_CONF_TAKE1: 指令讀入一個參數
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
//遇到該指令名字時調用的函數
ngx_http_hello_world,
//存儲位置,配置結構體+offset指示變量的具體存儲位置
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_hello_world_loc_conf_t, output_words),
NULL
},
ngx_null_command
};
//實現ngx_http_module_t接口,來管理http模塊的配置項,在http框架初始化時,會調用該模塊定義的回調方法
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
};
//定義ngx_module_t模塊,主要工作是利用前面定義的ngx_http_hello_world_module_ctx和ngx_http_hello_world_commands
//來對其中的ctx和commands成員變量進行賦值
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];
//建立ngx_buf_t,直接指向原內存地址,不對數據進行復制,節省內存
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);
//將ngx_http_core_loc_conf_t結構體的回調函數設爲ngx_http_hello_world_handle,
//在NGX_HTTP_CONTENT_PHASE階段,如果請求的主機名,URI與配置項所在的配置塊相匹配時,就調用該回調方法
clcf->handler = ngx_http_hello_world_handler;
ngx_conf_set_str_slot(cf, cmd, conf);
return NGX_CONF_OK;
}
- 添加配置項
在/usr/local/nginx/html文件夾中創建hello.html文件,把hello world寫入到hello.html文件中,然後在配置文件/usr/local/nginx/conf/nginx.conf中對應的http中添加:
server{
listen 7777; #端口
server_name 192.168.64.128;
location /
{
root html;
index hello.html;
}
}
- 添加模塊並編譯
在nginx源目錄下humeng@humeng-virtual-machine:~/nginx-1.14.2$ 進行:
sudo ./configure --add-module=./src/plugin/
sudo make
sudo make install
- 重啓Nginx,加載新配置
humeng@humeng-virtual-machine:/usr/local/nginx/sbin$ sudo ./nginx
humeng@humeng-virtual-machine:/usr/local/nginx/sbin$ sudo ./nginx -s reload
- 使用瀏覽器訪問