1. 程式人生 > >1. nginx添加自定義http模塊(簡單)

1. nginx添加自定義http模塊(簡單)

訪問 quest cmd return 頭部 true card char* 內存

步驟

1. 新建模塊目錄
2. 添加模塊配置文件
3. 編寫模塊源碼文件
4. 在主配置文件中配置訪問location
5. 編譯加入模塊文件
6. 測試

新建模塊目錄

mkdir /opt/nginx/ext/hello_world/

  

添加模塊配置文件

vim /opt/nginx/ext/hello_world/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"
CORE_LIBS="$CORE_LIBS -lpcre"

# ngx_addon_name 表示模塊名稱
# HTTP_MODULES 表示定義HTTP_MODULES模塊,多個模塊以空格分開,為了不覆蓋之前的模塊,使用$HTTP_MODULES代表已經存在的
# NGX_ADDON_SRCS 代表模塊代碼路徑
# CORE_LIBS 代表模塊需要的庫文件 

編寫模塊文件

文件直接放在模塊目錄下即可(vim /opt/nginx/ext/hello_world/ngx_http_hello_world_module.c)

定義HTTP模塊

static ngx_command_t ngx_http_hello_world_commands[] = { 
  {
    ngx_string("hello_world"),
    NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | \ 
      NGX_CONF_NOARGS,
    ngx_http_hello_world,
    NGX_HTTP_LOC_CONF_OFFSET,
    0,  
    NULL
  },  
  ngx_null_command
};

// hello_world: 這個與nginx.conf中定義的location中的名字一致
//  NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_NOARGS: 指定出現的位置,可以出現在location {}中
// nginx_http_hello_world: 這個ngx_command_t中的set成員,當某塊位置出現hello_world時候,nginx將會啟動ngx_http_hello_world方法,所以需要定義該函數

static ngx_http_module_t ngx_http_hello_world_module_ctx = { 
  NULL,  /* preconfiguration */
  NULL,  /* postconfiguration */
  NULL,  /* create main configuration */
  NULL,  /* init main configuration */
  NULL,  /* create server configuration */
  NULL,  /* merge server configuration */
  NULL,  /* create location configuration */
  NULL   /* merge location configuration */
};

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
};

// NGX_MODULE_V1 代表版本號
// ngx_http_hello_world_module_ctx 代表模塊上下文結構,HTTP框架要求,固定用法
// ngx_http_hello_world_commands 代表模塊的配置文件參數,這個在nginx.conf文件解析
// NGX_HTTP_MODULE 代表這是一個http模塊

  

定義模塊觸發函數

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;
    return NGX_CONF_OK;
}

// ngx_http_conf_get_module_loc_conf: 這個函數會首先找到hello_world配置所屬的配置塊
// handler: http框架在處理用戶請求進行到NGX_HTTP_CONTENT_PHASE階段,如果請求的主機域名,URL和hello_world相匹配,那麽就調用這handler指向的方法ngx_http_hello_world_handler

  

編寫請求處理方法handler

static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r)
{
    ngx_int_t rc = ngx_http_discard_request_body(r);
    if (rc != NGX_OK) {
        return rc;
    }

    ngx_str_t type = ngx_string("text/plain");
    ngx_str_t response = ngx_string("Hello World");
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = response.len;
    r->headers_out.content_type = type;

    rc = ngx_http_send_header(r);//發送頭部
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
        return rc;
    }

    ngx_buf_t *b;
    b = ngx_create_temp_buf(r->pool, response.len);//異步發送,要用堆內存空間
    if (b == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ngx_memcpy(b->pos, response.data, response.len);
    b->last = b->pos + response.len;
    b->last_buf = 1;

    ngx_chain_t out;
    out.buf = b;
    out.next = NULL;

    return ngx_http_output_filter(r, &out);//向用戶發送響應包
}

  

完整的代碼匯總

#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>

static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r);

static char* ngx_http_hello_world(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

static ngx_command_t ngx_http_hello_world_commands[] = {
{
    ngx_string("hello_world"),
    NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF |     NGX_CONF_NOARGS,
    ngx_http_hello_world,
    NGX_HTTP_LOC_CONF_OFFSET,
    0,
    NULL
    },
    ngx_null_command
};

static ngx_http_module_t ngx_http_hello_world_module_ctx = {
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL
};

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) {
    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;

    return NGX_CONF_OK;
}

static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r) {
    ngx_int_t rc = ngx_http_discard_request_body(r);
    if (rc != NGX_OK) {
    	return rc;
    }

    ngx_str_t type = ngx_string("text/plain");
    ngx_str_t response = ngx_string("Hello World");
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = response.len;
    r->headers_out.content_type = type;

    rc = ngx_http_send_header(r);
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
    	return rc;
    }

    ngx_buf_t *b;
    b = ngx_create_temp_buf(r->pool, response.len);
    if (b == NULL) {
    	return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ngx_memcpy(b->pos, response.data, response.len);
    b->last = b->pos + response.len;
    b->last_buf = 1;

    ngx_chain_t out;
    out.buf = b;
    out.next = NULL;

    return ngx_http_output_filter(r, &out);
}

  

在主配置文件中配置訪問location

vim /etc/nginx

添加 location / {hello_world};
server {
	...
	location / { 
          hello_world;
        }
        
    ...
}

  

編譯加入模塊文件

./configure --add-module=/opt/nginx/ext/hello_world/

make && make install

  

測試

/usr/local/nginx/sbin/nginx

curl http://localhost

  

1. nginx添加自定義http模塊(簡單)