在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Linux/ 示例: hello handler 模塊
示例: hello handler 模塊
什么是 Nginx
handler 模塊的掛載
Nginx 特點(diǎn)
handler 模塊簡(jiǎn)介
初探 Nginx 架構(gòu)
Nginx 的模塊化體系結(jié)構(gòu)
更多 handler 模塊示例分析
Nginx 基礎(chǔ)概念
upstream 模塊簡(jiǎn)介
Nginx 的請(qǐng)求處理
過(guò)濾模塊簡(jiǎn)介
基本數(shù)據(jù)結(jié)構(gòu)
模塊的基本結(jié)構(gòu)
負(fù)載均衡模塊
過(guò)濾模塊的分析
core 模塊
handler 模塊的基本結(jié)構(gòu)
Nginx 的配置系統(tǒng)
handler 的編寫步驟
handler 模塊的編譯和使用
event 模塊

示例: hello handler 模塊

在前面已經(jīng)看到了這個(gè) hello handler module 的部分重要的結(jié)構(gòu)。該模塊提供了 2 個(gè)配置指令,僅可以出現(xiàn)在 location 指令的作用域中。這兩個(gè)指令是 hello_string, 該指令接受一個(gè)參數(shù)來(lái)設(shè)置顯示的字符串。如果沒(méi)有跟參數(shù),那么就使用默認(rèn)的字符串作為響應(yīng)字符串。

另一個(gè)指令是 hello_counter,如果設(shè)置為 on,則會(huì)在響應(yīng)的字符串后面追加 Visited Times:的字樣,以統(tǒng)計(jì)請(qǐng)求的次數(shù)。

這里有兩點(diǎn)注意一下:

  1. 對(duì)于 flag 類型的配置指令,當(dāng)值為 off 的時(shí)候,使用 ngx_conf_set_flag_slot 函數(shù),會(huì)轉(zhuǎn)化為 0,為on,則轉(zhuǎn)化為非 0。
  2. 另外一個(gè)是,我提供了 merge_loc_conf 函數(shù),但是卻沒(méi)有設(shè)置到模塊的上下文定義中。這樣有一個(gè)缺點(diǎn),就是如果一個(gè)指令沒(méi)有出現(xiàn)在配置文件中的時(shí)候,配置信息中的值,將永遠(yuǎn)會(huì)保持在 create_loc_conf 中的初始化的值。那如果,在類似 create_loc_conf 這樣的函數(shù)中,對(duì)創(chuàng)建出來(lái)的配置信息的值,沒(méi)有設(shè)置為合理的值的話,后面用戶又沒(méi)有配置,就會(huì)出現(xiàn)問(wèn)題。

下面來(lái)完整的給出 ngx_http_hello_module 模塊的完整代碼。

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

    typedef struct
    {
        ngx_str_t hello_string;
        ngx_int_t hello_counter;
    }ngx_http_hello_loc_conf_t;

    static ngx_int_t ngx_http_hello_init(ngx_conf_t *cf);

    static void *ngx_http_hello_create_loc_conf(ngx_conf_t *cf);

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

    static ngx_command_t ngx_http_hello_commands[] = {
       { 
            ngx_string("hello_string"),
            NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
            ngx_http_hello_string,
            NGX_HTTP_LOC_CONF_OFFSET,
            offsetof(ngx_http_hello_loc_conf_t, hello_string),
            NULL },

        { 
            ngx_string("hello_counter"),
            NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
            ngx_http_hello_counter,
            NGX_HTTP_LOC_CONF_OFFSET,
            offsetof(ngx_http_hello_loc_conf_t, hello_counter),
            NULL },               

        ngx_null_command
    };

    /* 
    static u_char ngx_hello_default_string[] = "Default String: Hello, world!";
    */
    static int ngx_hello_visited_times = 0; 

    static ngx_http_module_t ngx_http_hello_module_ctx = {
        NULL,                          /* preconfiguration */
        ngx_http_hello_init,           /* postconfiguration */

        NULL,                          /* create main configuration */
        NULL,                          /* init main configuration */

        NULL,                          /* create server configuration */
        NULL,                          /* merge server configuration */

        ngx_http_hello_create_loc_conf, /* create location configuration */
        NULL                            /* merge location configuration */
    };

    ngx_module_t ngx_http_hello_module = {
        NGX_MODULE_V1,
        &ngx_http_hello_module_ctx,    /* module context */
        ngx_http_hello_commands,       /* module directives */
        NGX_HTTP_MODULE,               /* module type */
        NULL,                          /* init master */
        NULL,                          /* init module */
        NULL,                          /* init process */
        NULL,                          /* init thread */
        NULL,                          /* exit thread */
        NULL,                          /* exit process */
        NULL,                          /* exit master */
        NGX_MODULE_V1_PADDING
    };

    static ngx_int_t
    ngx_http_hello_handler(ngx_http_request_t *r)
    {
        ngx_int_t    rc;
        ngx_buf_t   *b;
        ngx_chain_t  out;
        ngx_http_hello_loc_conf_t* my_conf;
        u_char ngx_hello_string[1024] = {0};
        ngx_uint_t content_length = 0;

        ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "ngx_http_hello_handler is called!");

        my_conf = ngx_http_get_module_loc_conf(r, ngx_http_hello_module);
        if (my_conf->hello_string.len == 0 )
        {
            ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "hello_string is empty!");
            return NGX_DECLINED;
        }

        if (my_conf->hello_counter == NGX_CONF_UNSET
            || my_conf->hello_counter == 0)
        {
            ngx_sprintf(ngx_hello_string, "%s", my_conf->hello_string.data);
        }
        else
        {
            ngx_sprintf(ngx_hello_string, "%s Visited Times:%d", my_conf->hello_string.data, 
                ++ngx_hello_visited_times);
        }
        ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "hello_string:%s", ngx_hello_string);
        content_length = ngx_strlen(ngx_hello_string);

        /* we response to 'GET' and 'HEAD' requests only */
        if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
            return NGX_HTTP_NOT_ALLOWED;
        }

        /* discard request body, since we don't need it here */
        rc = ngx_http_discard_request_body(r);

        if (rc != NGX_OK) {
            return rc;
        }

        /* set the 'Content-type' header */
        /*
         *r->headers_out.content_type.len = sizeof("text/html") - 1;
         *r->headers_out.content_type.data = (u_char *)"text/html";
                 */
        ngx_str_set(&r->headers_out.content_type, "text/html");

        /* send the header only, if the request type is http 'HEAD' */
        if (r->method == NGX_HTTP_HEAD) {
            r->headers_out.status = NGX_HTTP_OK;
            r->headers_out.content_length_n = content_length;

            return ngx_http_send_header(r);
        }

        /* allocate a buffer for your response body */
        b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
        if (b == NULL) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        /* attach this buffer to the buffer chain */
        out.buf = b;
        out.next = NULL;

        /* adjust the pointers of the buffer */
        b->pos = ngx_hello_string;
        b->last = ngx_hello_string + content_length;
        b->memory = 1;    /* this buffer is in memory */
        b->last_buf = 1;  /* this is the last buffer in the buffer chain */

        /* set the status line */
        r->headers_out.status = NGX_HTTP_OK;
        r->headers_out.content_length_n = content_length;

        /* send the headers of your response */
        rc = ngx_http_send_header(r);

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

        /* send the buffer chain of your response */
        return ngx_http_output_filter(r, &out);
    }

    static void *ngx_http_hello_create_loc_conf(ngx_conf_t *cf)
    {
        ngx_http_hello_loc_conf_t* local_conf = NULL;
        local_conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_hello_loc_conf_t));
        if (local_conf == NULL)
        {
            return NULL;
        }

        ngx_str_null(&local_conf->hello_string);
        local_conf->hello_counter = NGX_CONF_UNSET;

        return local_conf;
    } 

    /*
    static char *ngx_http_hello_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
    {
        ngx_http_hello_loc_conf_t* prev = parent;
        ngx_http_hello_loc_conf_t* conf = child;

        ngx_conf_merge_str_value(conf->hello_string, prev->hello_string, ngx_hello_default_string);
        ngx_conf_merge_value(conf->hello_counter, prev->hello_counter, 0);

        return NGX_CONF_OK;
    }*/

    static char *
    ngx_http_hello_string(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {

        ngx_http_hello_loc_conf_t* local_conf;

        local_conf = conf;
        char* rv = ngx_conf_set_str_slot(cf, cmd, conf);

        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "hello_string:%s", local_conf->hello_string.data);

        return rv;
    }

    static char *ngx_http_hello_counter(ngx_conf_t *cf, ngx_command_t *cmd,
        void *conf)
    {
        ngx_http_hello_loc_conf_t* local_conf;

        local_conf = conf;

        char* rv = NULL;

        rv = ngx_conf_set_flag_slot(cf, cmd, conf);

        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "hello_counter:%d", local_conf->hello_counter);
        return rv;    
    }

    static ngx_int_t
    ngx_http_hello_init(ngx_conf_t *cf)
    {
        ngx_http_handler_pt        *h;
        ngx_http_core_main_conf_t  *cmcf;

        cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

        h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
        if (h == NULL) {
            return NGX_ERROR;
        }

        *h = ngx_http_hello_handler;

        return NGX_OK;
    }

通過(guò)上面一些介紹,我相信大家都能對(duì)整個(gè)示例模塊有一個(gè)比較好的理解。唯一可能感覺(jué)有些理解困難的地方在于ngx_http_hello_handler 函數(shù)里面產(chǎn)生和設(shè)置輸出。但其實(shí)大家在本書的前面的相關(guān)章節(jié)都可以看到對(duì) ngx_buf_t 和 request 等相關(guān)數(shù)據(jù)結(jié)構(gòu)的說(shuō)明。如果仔細(xì)看了這些地方的說(shuō)明的話,應(yīng)該對(duì)這里代碼的實(shí)現(xiàn)就比較容易理解了。因此,這里不再贅述解釋。