【深入理解Nginx】編寫Hello World模塊

第三章 編寫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
  • 使用瀏覽器訪問

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章