Nginx教程
01、关于 Nginx
02、什么是 Nginx
03、Nginx 的特点
04、初探 Nginx 架构
05、Nginx 基础概念
06、Nginx 基本数据结构
07、Nginx 的配置系统
08、Nginx 的模块化体系结构
09、Nginx 的请求处理
10、Nginx handler 模块简介
11、Nginx 模块的基本结构
12、Nginx handler 模块的基本结构
13、Nginx handler 模块的挂载
14、Nginx handler 的编写步骤
15、Nginx 示例_ hello handler 模块
16、Nginx handler 模块的编译和使用
17、Nginx 更多 handler 模块示例分析
18、Nginx 过滤模块简介
19、Nginx 过滤模块的分析
20、Nginx upstream 模块简介
21、Nginx 负载均衡模块
22、Nginx core 模块
23、Nginx event 模块
24、Nginx 配置文件nginx.conf中文详解
本文档使用 MrDoc 发布
-
+
首页
15、Nginx 示例_ hello handler 模块
### **示例: hello handler 模块** ------------ 在前面已经看到了这个 hello handler module 的部分重要的结构。该模块提供了 2 个配置指令,仅可以出现在 location 指令的作用域中。这两个指令是 hello_string, 该指令接受一个参数来设置显示的字符串。如果没有跟参数,那么就使用默认的字符串作为响应字符串。 另一个指令是 hello_counter,如果设置为 on,则会在响应的字符串后面追加 Visited Times:的字样,以统计请求的次数。 这里有两点注意一下: 1、 对于flag类型的配置指令,当值为off的时候,使用ngx_conf_set_flag_slot函数,会转化为0,为on,则转化为非0; 2、 另外一个是,我提供了merge_loc_conf函数,但是却没有设置到模块的上下文定义中这样有一个缺点,就是如果一个指令没有出现在配置文件中的时候,配置信息中的值,将永远会保持在create_loc_conf中的初始化的值那如果,在类似create_loc_conf这样的函数中,对创建出来的配置信息的值,没有设置为合理的值的话,后面用户又没有配置,就会出现问题; 下面来完整的给出 ngx_http_hello_module 模块的完整代码。 ```yaml #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; ``` 通过上面一些介绍,我相信大家都能对整个示例模块有一个比较好的理解。唯一可能感觉有些理解困难的地方在于ngx_http_hello_handler 函数里面产生和设置输出。但其实大家在本书的前面的相关章节都可以看到对 ngx_buf_t 和 request 等相关数据结构的说明。如果仔细看了这些地方的说明的话,应该对这里代码的实现就比较容易理解了。因此,这里不再赘述解释。
李智
2025年3月17日 13:32
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码