文章9:Nginx模块开发详细介绍--以HelloWorld模块为例
2015-01-24 10:46
471 查看
文章内容: 一结构体介绍 1.结构体ngx_command_t 模块的指令 1.1结构体原型 1.2结构体成员变量说明 1.3 实例 2.ngx_conf_t模块的配置结构体 2.1结构体原型 3.ngx_http_module_t结构体 模块上下文 3.1结构体原型 3.2结构体作用: 3.3实例 4.ngx_module_t结构体 模块定义 4.1结构体原型: 4.2结构体作用: 4.3实例 二.处理模块、过滤模块和负载均衡模块 2.1. 剖析处理模块(非代理) 2.1.1获得位置配置结构体 2.1.2产生回复 2.1.3发送HTTP头部 2.1.4 发送HTTP主体 2.1.5最后附上hello_world模块的完整代码 2.2剖析配置文件config 2.2.1.内容 2.2.2.作用 2.2.3.对应 三、综上所述,如何安装HelloWorld模块呢? |
1、ngx_command_t模块的指令
[align=left]1.1结构体原型[/align] [align=left]struct ngx_command_s {[/align] [align=left] ngx_str_t name;[/align] [align=left] ngx_uint_t type;[/align] [align=left] char *(* set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);[/align] [align=left] ngx_uint_t conf;[/align] [align=left] ngx_uint_t offset;[/align] [align=left] void * post;[/align] [align=left]};[/align] |
1.2结构体成员变量说明: name:是指令的字符串(也就是包含指令名称),不包含空格(有空格的话,就是命令的参数), type:标识的集合。表明这个指令是在哪里出现是合法的、指令的参数个数。 标识一般是下面多个值的位或。 一、NGX_HTTP_MAIN_CONF:指令出现在全局配置部分是合法的 NGX_HTTP_SRV_CONF NGX_HTTP_LOC_CONF NGX_HTTP_UPS_CONF 二、NGX_CONF_NOARGS:指令没有参数 NGX_CONF_TAKE1:指令读入一个参数 .... NGX_CONF_TAKE7:指令读入7个参数 三、NGX_CONF_FLAG:指令读入一个布尔型数据 NGX_CONF_1MORE:指令至少读入1个参数 NGX_CONF_2MORE:指令至少读入2个参数 set:char *(* set )(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 结构体成员set是一个函数指针,用来设定模块的配置;典型地,这个函数会转化读入指令传进来的参数,然后将合适的值保存到配置结构体。这个设定函数有三个参数: 1)指向ngx_conf_t结构体的指针,包含从配置文件中指令传过来的参数 2)指向当前ngx_command_t结构体的指针 3)指向自定义模块配置结构体的指针void *conf 这个设定函数set在指令被遇到的时候就会调用。 后三个参数: 在自定义的配置结构体void *conf中,Nginx提供了多个函数用来保存特定类型的数据,这些函数包含有: ngx_conf_set_flag_slot::将on或off转化为 ngx_conf_set_str_slot:将字符串保存为ngx_str_t类型 ngx_conf_set_num_slot:解析一个数字并保存为int类型 ngx_conf_set_size_slot:解析一个数据大小并保存为size_t类型 那这些内嵌函数怎么知道要把值保存在哪里呢? ngx_command_t接下来的两个成员 conf和 offset正好可用。 conf告诉 Nginx把这个值是放在全局配置部分、主机配置部分还是位置配置部分(NGX_HTTP_MAIN_CONF_OFFSET, NGX_HTTP_SRV_CONF_OFFSET或NGX_HTTP_LOC_CONF_OFFSET)。然后offset确定到底是保存在结构体的哪个位置。最后,post指向模块在读配置的时候需要的一些零碎变量。一般它是NULL。 这个ngx_command_t数组在读入ngx_null_command后停止 |
1.3实例: static ngx_command_t ngx_http_hello_world_commands[]={ [align=left] {[/align] [align=left] ngx_string( "hello_world"),[/align] [align=left] NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,[/align] [align=left] ngx_http_hello_world,[/align] [align=left] 0,[/align] [align=left] 0,[/align] [align=left] NULL[/align] [align=left] },[/align] [align=left] ngx_null_command[/align] [align=left]};[/align] |
[align=left]2.1结构体原型[/align] [align=left]struct ngx_conf_s {[/align] [align=left] char * name;[/align] [align=left] ngx_array_t * args;[/align] [align=left] ngx_cycle_t * cycle;[/align] [align=left] ngx_pool_t * pool;[/align] [align=left] ngx_pool_t * temp_pool;[/align] [align=left] ngx_conf_file_t * conf_file;[/align] [align=left] ngx_log_t * log;[/align] [align=left] void * ctx;[/align] [align=left] ngx_uint_t module_type;[/align] [align=left] ngx_uint_t cmd_type;[/align] [align=left] ngx_conf_handler_pt handler;[/align] [align=left] char * handler_conf;[/align] [align=left]};[/align] |
[align=left]3.1结构体原型[/align] [align=left]typedef struct {[/align] [align=left] ngx_int_t (* preconfiguration)(ngx_conf_t *cf);//在读入配置文件前调用[/align] [align=left] ngx_int_t (* postconfiguration)(ngx_conf_t *cf);//在读入配置文件后调用[/align] [align=left] void *(* create_main_conf)(ngx_conf_t *cf);//在创建全局部分配置时调用(比如,用来分配空间和设置默认值)[/align] char *(* init_main_conf)(ngx_conf_t *cf, void *conf);//在初始化全局部分的配置时调用(比如,把原来的默认值用nginx.conf 读到的值来覆盖) [align=left] void *(* create_srv_conf)(ngx_conf_t *cf);//在创建主机部分的配置时调用[/align] [align=left] char *(* merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);//与全局部分配置合并时调用[/align] [align=left] void *(* create_loc_conf)(ngx_conf_t *cf);//创建位置部分的配置时掉用[/align] [align=left] char *(* merge_loc_conf )(ngx_conf_t *cf, void *prev, void *conf);//与主机部分配置合并时调用[/align] [align=left]} ngx_http_module_t;[/align] |
3.2结构体作用: 静态的ngx_http_module_t结构体,包含一大把函数引用。用来创建三个部分的配置和合并配置。一般结构体命名为ngx_http_<module_name>_module_ctx。 |
大多数处理模块只使用最后两个:一个函数用来为特定的位置部分的配置结构体分配内存(称为ngx_http_<module name>_create_loc_conf),另外一个函数用来设定默认值和与继承过来的配置合并(称为ngx_http_<module name>_merge_loc_conf)。这个合并函数负责检验读入的数值是否有效,并设定一些默认值 |
3.3实例: static ngx_http_module_t ngx_http_hello_world_module_ctx={ [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL[/align] [align=left]};[/align] |
[align=left]4.1结构体原型[/align] [align=left]struct ngx_module_s {[/align] [align=left] ngx_uint_t ctx_index;[/align] [align=left] ngx_uint_t index;[/align] [align=left] ngx_uint_t spare0;[/align] [align=left] ngx_uint_t spare1;[/align] [align=left] ngx_uint_t spare2;[/align] [align=left] ngx_uint_t spare3;[/align] [align=left] ngx_uint_t version;[/align] void * ctx;/* module context */ ngx_command_t * commands;/* module directives */ ngx_uint_t type;/* module type */ ngx_int_t (* init_master)(ngx_log_t *log);/* init master */ ngx_int_t (* init_module)(ngx_cycle_t *cycle);/* init module */ ngx_int_t (* init_process)(ngx_cycle_t *cycle);/* init process */ ngx_int_t (* init_thread)(ngx_cycle_t *cycle);/* init thread */ void (* exit_thread)(ngx_cycle_t *cycle);/* exit thread */ void (* exit_process)(ngx_cycle_t *cycle);/* exit process */ void (* exit_master)(ngx_cycle_t *cycle);/* exit master */ [align=left] uintptr_t spare_hook0;[/align] [align=left] uintptr_t spare_hook1;[/align] [align=left] uintptr_t spare_hook2;[/align] [align=left] uintptr_t spare_hook3;[/align] [align=left] uintptr_t spare_hook4;[/align] [align=left] uintptr_t spare_hook5;[/align] [align=left] uintptr_t spare_hook6;[/align] [align=left] uintptr_t spare_hook7;[/align] [align=left]}; [/align] |
4.2结构体作用: 这个结构体变量名为为ngx_http_<module_name>_module。 它包含模块的主要内容和指令的执行部分,也有一些回调函数(退出线程,推退出进程等等)。这些函数的定义是把数据处理关联到特定模块的关键。 在进程/线程退出的时候,模块可以添加一些回调函数来运行,但大多数模块用不到。 |
4.3实例: ngx_module_t ngx_http_hello_world_module={ [align=left] NGX_MODULE_V1,[/align] [align=left] &ngx_http_hello_world_module_ctx,[/align] [align=left] ngx_http_hello_world_commands,[/align] [align=left] NGX_HTTP_MODULE,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NGX_MODULE_V1_PADDING[/align] [align=left]};[/align] |
2.1. 剖析处理模块(非代理)
处理模块一般做四样东西:获得位置配置结构体,产生合适的回复,发送HTTP头部和发送HTTP主体。它只有一个变量--请求结构体。这个结构体有很多关于客户端请求的有用信息,比如请求方法(request
method),URI和请求头部。我们会一步一步分析整个过程。
2.1.1获得位置配置结构体
这部分很简单,所有你需要做的事根据当前的请求结构体和模块定义,调用ngx_http_get_module_loc_conf,获得当前的配置结构体。
实例: [align=left]static char *ngx_http_hello_world (ngx_conf_t *cf,ngx_command_t *cmd, void *conf)[/align] [align=left]{[/align] [align=left] ngx_http_core_loc_conf_t *clcf;[/align] [align=left] [/align] [align=left] clcf=ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);[/align] [align=left] clcf-> handler=ngx_http_hello_world_handler;[/align] [align=left] return NGX_CONF_OK;[/align] [align=left]}[/align] |
1.结构体ngx_http_request_t
[align=left]struct ngx_http_request_s {[/align] uint32_t signature; /* "HTTP" */ [align=left] ngx_connection_t * connection;[/align] void ** ctx; void ** main_conf; void ** srv_conf; void ** loc_conf; [align=left] ngx_http_event_handler_pt read_event_handler;[/align] [align=left] ngx_http_event_handler_pt write_event_handler;[/align] [align=left]#if (NGX_HTTP_CACHE)[/align] [align=left] ngx_http_cache_t * cache;[/align] [align=left]#endif[/align] [align=left] ngx_http_upstream_t * upstream;[/align] [align=left] ngx_array_t * upstream_states;[/align] [align=left] /* of ngx_http_upstream_state_t */[/align] [align=left] ngx_pool_t *pool;[/align] [align=left] ngx_buf_t * header_in;[/align] [align=left] ngx_http_headers_in_t headers_in;[/align] [align=left] ngx_http_headers_out_t headers_out;[/align] [align=left] ngx_http_request_body_t * request_body;[/align] [align=left] time_t lingering_time;[/align] [align=left] time_t start_sec;[/align] [align=left] ngx_msec_t start_msec;[/align] [align=left] ngx_uint_t method;[/align] [align=left] ngx_uint_t http_version;[/align] [align=left] ngx_str_t request_line;[/align] [align=left] ngx_str_t uri;[/align] [align=left] ngx_str_t args;[/align] [align=left] ngx_str_t exten;[/align] [align=left] ngx_str_t unparsed_uri;[/align] [align=left] ngx_str_t method_name;[/align] [align=left] ngx_str_t http_protocol;[/align] [align=left] ngx_chain_t * out;[/align] [align=left] ngx_http_request_t * main;[/align] [align=left] ngx_http_request_t * parent;[/align] [align=left] ngx_http_postponed_request_t * postponed;[/align] [align=left] ngx_http_post_subrequest_t * post_subrequest;[/align] [align=left] ngx_http_posted_request_t * posted_requests;[/align] [align=left] ngx_http_virtual_names_t * virtual_names;[/align] [align=left] ngx_int_t phase_handler;[/align] [align=left] ngx_http_handler_pt content_handler;[/align] [align=left] ngx_uint_t access_code;[/align] [align=left] ngx_http_variable_value_t * variables;[/align] [align=left]#if (NGX_PCRE)[/align] [align=left] ngx_uint_t ncaptures;[/align] int * captures; [align=left] u_char * captures_data;[/align] [align=left]#endif[/align] [align=left] size_t limit_rate;[/align] [align=left] /* used to learn the Apache compatible response length without a header */[/align] [align=left] size_t header_size;[/align] [align=left] off_t request_length;[/align] [align=left] ngx_uint_t err_status;[/align] [align=left] ngx_http_connection_t * http_connection;[/align] [align=left] ngx_http_log_handler_pt log_handler;[/align] [align=left] ngx_http_cleanup_t * cleanup;[/align] [align=left] unsigned subrequests:8;[/align] [align=left] unsigned count:8;[/align] [align=left] unsigned blocked:8;[/align] [align=left] unsigned aio:1;[/align] [align=left] unsigned http_state:4;[/align] [align=left] /* URI with "/." and on Win32 with "//" */[/align] [align=left] unsigned complex_uri:1;[/align] [align=left] /* URI with "%" */[/align] [align=left] unsigned quoted_uri:1;[/align] [align=left] /* URI with "+" */[/align] [align=left] unsigned plus_in_uri:1;[/align] [align=left] /* URI with " " */[/align] [align=left] unsigned space_in_uri:1;[/align] [align=left] unsigned invalid_header:1;[/align] [align=left] unsigned add_uri_to_alias:1;[/align] [align=left] unsigned valid_location:1;[/align] [align=left] unsigned valid_unparsed_uri:1;[/align] [align=left] unsigned uri_changed:1;[/align] [align=left] unsigned uri_changes:4;[/align] [align=left] unsigned request_body_in_single_buf:1;[/align] [align=left] unsigned request_body_in_file_only:1;[/align] [align=left] unsigned request_body_in_persistent_file:1;[/align] [align=left] unsigned request_body_in_clean_file:1;[/align] [align=left] unsigned request_body_file_group_access:1;[/align] [align=left] unsigned request_body_file_log_level:3;[/align] [align=left] unsigned subrequest_in_memory:1;[/align] [align=left] unsigned waited:1;[/align] [align=left]#if (NGX_HTTP_CACHE)[/align] [align=left] unsigned cached:1;[/align] [align=left]#endif[/align] [align=left]#if (NGX_HTTP_GZIP)[/align] [align=left] unsigned gzip_tested:1;[/align] [align=left] unsigned gzip_ok:1;[/align] [align=left] unsigned gzip_vary:1;[/align] [align=left]#endif[/align] [align=left] unsigned proxy:1;[/align] [align=left] unsigned bypass_cache:1;[/align] [align=left] unsigned no_cache:1;[/align] [align=left] /*[/align] [align=left] * instead of using the request context data in[/align] [align=left] * ngx_http_limit_conn_module and ngx_http_limit_req_module[/align] [align=left] * we use the single bits in the request structure[/align] [align=left] */[/align] [align=left] unsigned limit_conn_set:1;[/align] [align=left] unsigned limit_req_set:1;[/align] [align=left]#if 0[/align] unsigned cacheable:1; [align=left]#endif[/align] [align=left] unsigned pipeline:1;[/align] [align=left] unsigned plain_http:1;[/align] [align=left] unsigned chunked:1;[/align] [align=left] unsigned header_only:1;[/align] [align=left] unsigned keepalive:1;[/align] [align=left] unsigned lingering_close:1;[/align] [align=left] unsigned discard_body:1;[/align] [align=left] unsigned internal:1;[/align] [align=left] unsigned error_page:1;[/align] [align=left] unsigned ignore_content_encoding:1;[/align] [align=left] unsigned filter_finalize:1;[/align] [align=left] unsigned post_action:1;[/align] [align=left] unsigned request_complete:1;[/align] [align=left] unsigned request_output:1;[/align] [align=left] unsigned header_sent:1;[/align] [align=left] unsigned expect_tested:1;[/align] [align=left] unsigned root_tested:1;[/align] [align=left] unsigned done:1;[/align] [align=left] unsigned logged:1;[/align] [align=left] unsigned buffered:4;[/align] [align=left] unsigned main_filter_need_in_memory:1;[/align] [align=left] unsigned filter_need_in_memory:1;[/align] [align=left] unsigned filter_need_temporary:1;[/align] [align=left] unsigned allow_ranges:1;[/align] [align=left]#if (NGX_STAT_STUB)[/align] [align=left] unsigned stat_reading:1;[/align] [align=left] unsigned stat_writing:1;[/align] [align=left]#endif[/align] [align=left] /* used to parse HTTP headers */[/align] [align=left] ngx_uint_t state;[/align] [align=left] ngx_uint_t header_hash;[/align] [align=left] ngx_uint_t lowcase_index;[/align] [align=left] u_char lowcase_header[NGX_HTTP_LC_HEADER_LEN];[/align] [align=left] u_char * header_name_start;[/align] [align=left] u_char * header_name_end;[/align] [align=left] u_char * header_start;[/align] [align=left] u_char * header_end;[/align] [align=left] /*[/align] [align=left] * a memory that can be reused after parsing a request line[/align] [align=left] * via ngx_http_ephemeral_t[/align] [align=left] */[/align] [align=left] u_char * uri_start;[/align] [align=left] u_char * uri_end;[/align] [align=left] u_char * uri_ext;[/align] [align=left] u_char * args_start;[/align] [align=left] u_char * request_start;[/align] [align=left] u_char * request_end;[/align] [align=left] u_char * method_end;[/align] [align=left] u_char * schema_start;[/align] [align=left] u_char * schema_end;[/align] [align=left] u_char * host_start;[/align] [align=left] u_char * host_end;[/align] [align=left] u_char * port_start;[/align] [align=left] u_char * port_end;[/align] [align=left] unsigned http_minor:16;[/align] [align=left] unsigned http_major:16;[/align] [align=left]};[/align] |
结构体成员变量说明: 1)uri:请求路径,比如:“/query.cgi” 2) args:是在问号之后请求的参数,比如:“name=john” 3)headers_in有很多有用的东西,如cookie和浏览器信息。 |
回复头部存在于被称为headers_out的结构体中。它包含在请求结构体中。这个处理函数生成头部变量,然后调用ngx_http_send_header(r)函数
ngx_http_headers_out_t结构体 加粗为有用部分
[align=left]typedef struct {[/align] [align=left] ngx_list_t headers;[/align] [align=left] ngx_uint_t status;[/align] [align=left] ngx_str_t status_line;[/align] [align=left] ngx_table_elt_t * server;[/align] [align=left] ngx_table_elt_t * date;[/align] [align=left] ngx_table_elt_t * content_length;[/align] [align=left] ngx_table_elt_t *content_encoding;[/align] [align=left] ngx_table_elt_t * location;[/align] [align=left] ngx_table_elt_t * refresh;[/align] [align=left] ngx_table_elt_t * last_modified;[/align] [align=left] ngx_table_elt_t * content_range;[/align] [align=left] ngx_table_elt_t * accept_ranges;[/align] [align=left] ngx_table_elt_t * www_authenticate;[/align] [align=left] ngx_table_elt_t * expires;[/align] [align=left] ngx_table_elt_t * etag;[/align] [align=left] ngx_str_t * override_charset;[/align] [align=left] size_t content_type_len;[/align] [align=left] ngx_str_t content_type;[/align] [align=left] ngx_str_t charset;[/align] [align=left] u_char * content_type_lowcase;[/align] [align=left] ngx_uint_t content_type_hash;[/align] [align=left] ngx_array_t cache_control;[/align] [align=left] off_t content_length_n;[/align] [align=left] time_t date_time;[/align] [align=left] time_t last_modified_time;[/align] [align=left]} ngx_http_headers_out_t;[/align] |
[align=left]r->headers_out.status = NGX_HTTP_OK;[/align] [align=left]r->headers_out.content_length_n = 100;[/align] [align=left]r->headers_out.content_type.len = sizeof("image/gif") - 1;[/align] [align=left]r->headers_out.content_type.data = (u_char *) "image/gif";[/align] [align=left]ngx_http_send_header(r);[/align] |
[align=left]r->headers_out.content_encoding = ngx_list_push(&r-[/align] [align=left]>headers_out.headers);[/align] [align=left]if (r->headers_out.content_encoding == NULL) {[/align] [align=left]return NGX_ERROR;[/align] [align=left]}[/align] [align=left]r->headers_out.content_encoding->hash = 1;[/align] [align=left]r->headers_out.content_encoding->key.len = sizeof("Content-[/align] [align=left]Encoding") - 1;[/align] [align=left]r->headers_out.content_encoding->key.data = (u_char *) "Content-[/align] [align=left]Encoding";[/align] [align=left]r->headers_out.content_encoding->value.len = sizeof("deflate") -[/align] [align=left]1;[/align] [align=left]r->headers_out.content_encoding->value.data = (u_char *)[/align] [align=left]"deflate";[/align] [align=left]ngx_http_send_header(r);[/align] |
2.1.4 发送HTTP主体
现在模块已经产生了一个回复,把它放到内存中。需要为回复分配一块特别的buffer,并把这个buffer连接到一个链表,然后调用“send body”函数发送。
这些链表有什么用?在Nginx中,处理模块和过滤模块在处理完成后产生的回复都包含在缓冲中,每次产生一个buffer;每个链表成员保存指向下一个成员的指针,如果是最后的buffer,就置为NULL。这里我们简单地假定只有一个buffer成员。
首先,模块声明一块buffer和一条链表:
[align=left]ngx_buf_t *b;[/align] [align=left]ngx_chain_t out;[/align] |
[align=left]b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));[/align] [align=left]if (b == NULL) {[/align] [align=left]ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,[/align] [align=left]"Failed to allocate response buffer.");[/align] [align=left]return NGX_HTTP_INTERNAL_SERVER_ERROR;[/align] [align=left]}[/align] [align=left]b->pos = some_bytes; /* first position in memory of the data */[/align] [align=left]b->last = some_bytes + some_bytes_length; /* last position */[/align] [align=left]b->memory = 1; /* content is in read-only memory */[/align] [align=left]/* (i.e., filters should copy it rather than rewrite in place) */[/align] [align=left]b->last_buf = 1; /* there will be no more buffers in the request[/align] [align=left]*/[/align] |
[align=left]out.buf = b;[/align] [align=left]out.next = NULL;[/align] |
[align=left]return ngx_http_output_filter(r, &out);[/align] |
[align=left]static ngx_int_t ngx_http_hello_world_handler( ngx_http_request_t *r)[/align] [align=left]{[/align] [align=left] ngx_buf_t *b;[/align] [align=left] ngx_chain_t out;[/align] [align=left] r-> headers_out.content_type .len = sizeof("text/plain" )-1;[/align] [align=left] r-> headers_out.content_type .data=( u_char *) "text/plain" ;[/align] [align=left] b=ngx_pcalloc(r-> pool,sizeof (ngx_buf_t));[/align] [align=left] out. buf=b;[/align] [align=left] out. next=NULL;[/align] [align=left] b-> pos=ngx_hello_world;[/align] [align=left] b-> last=ngx_hello_world+sizeof(ngx_hello_world);[/align] [align=left] b-> memory=1;[/align] [align=left] b-> last_buf=1;[/align] [align=left] [/align] [align=left] r-> headers_out.status =NGX_HTTP_OK;[/align] [align=left] r-> headers_out.content_length_n =sizeof(ngx_hello_world);[/align] [align=left] ngx_http_send_header(r);[/align] [align=left] [/align] [align=left] return ngx_http_output_filter(r,&out);[/align] [align=left]}[/align] |
问题:为什么会有变量last_buf,什么时候我们才能说这条链表结束了,并把next设为NULL?
回答:链表可能不完全的,比如,有多个buffer的时候,但是不是所有的buffer都在这个请求或者回复中。所以一些buffer是链表的结尾,而不是请求的结尾。这意味着模块判断是否是请求的结尾,并设置相应的值。
2.1.5最后附上hello_world模块的完整代码
[align=left]#include <ngx_config.h>[/align] [align=left]#include <ngx_core.h>[/align] [align=left]#include <ngx_http.h>[/align] [align=left]#include <ngx_buf.h>[/align] static char *ngx_http_hello_world(ngx_conf_t *cf , ngx_command_t *cmd,void *conf); [align=left]static ngx_command_t ngx_http_hello_world_commands []={[/align] [align=left] {[/align] [align=left] ngx_string( "hello_world"),[/align] [align=left] NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,[/align] [align=left] ngx_http_hello_world,[/align] [align=left] 0,[/align] [align=left] 0,[/align] [align=left] NULL[/align] [align=left] },[/align] [align=left] ngx_null_command[/align] [align=left]};[/align] static u_char ngx_hello_world[]="hello world"; [align=left]static ngx_http_module_t ngx_http_hello_world_module_ctx={[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL[/align] [align=left]};[/align] ngx_module_t ngx_http_hello_world_module={ //模块 [align=left] NGX_MODULE_V1,[/align] [align=left] &ngx_http_hello_world_module_ctx,[/align] [align=left] ngx_http_hello_world_commands,[/align] [align=left] NGX_HTTP_MODULE,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NULL,[/align] [align=left] NGX_MODULE_V1_PADDING[/align] [align=left]};[/align] [align=left]static ngx_int_t ngx_http_hello_world_handler( ngx_http_request_t *r)[/align] [align=left]{[/align] [align=left] ngx_buf_t *b;[/align] [align=left] ngx_chain_t out;[/align] [align=left] r-> headers_out.content_type .len = sizeof("text/plain" )-1;[/align] [align=left] r-> headers_out.content_type .data=( u_char *) "text/plain" ;[/align] [align=left] b=ngx_pcalloc(r-> pool,sizeof (ngx_buf_t));[/align] [align=left] out. buf=b;[/align] [align=left] out. next=NULL;[/align] b-> pos=ngx_hello_world; //自定义变量 [align=left] b-> last=ngx_hello_world+sizeof(ngx_hello_world);[/align] [align=left] b-> memory=1;[/align] [align=left] b-> last_buf=1;[/align] [align=left] [/align] [align=left] r-> headers_out.status =NGX_HTTP_OK;[/align] [align=left] r-> headers_out.content_length_n =sizeof(ngx_hello_world);[/align] [align=left] ngx_http_send_header(r);[/align] [align=left] [/align] [align=left] return ngx_http_output_filter(r,&out);[/align] [align=left]}[/align] [align=left]static char *ngx_http_hello_world (ngx_conf_t *cf,ngx_command_t *cmd, void *conf)[/align] [align=left]{[/align] [align=left] ngx_http_core_loc_conf_t *clcf;[/align] [align=left] [/align] [align=left] clcf=ngx_http_conf_get_module_loc_conf(cf,ngx_http_core_module);[/align] [align=left] clcf-> handler=ngx_http_hello_world_handler;[/align] [align=left] return NGX_CONF_OK;[/align] [align=left]}[/align] |
2.2.1.内容
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_dirx_http_hello_world_module.c" CORE_LIBS="$CORE_LIBS -lpcre" |
通过NGX_ADDON_SRCS找到源码文件, 通过HTTP_MODULES找到模块,就可以找到ctx和command(ngx_init_cycle函数中进行),并可以对HTTP请求进行处理。 |
三、综上所述,如何安装HelloWorld模块呢?
简要概括如下:除了第四步以外,其余都参考/article/1653059.html 中相关内容
1.下载Nginx最新代码
2.建立模块目录与代码
3.创建Makefile文件
4.直接$make && make install就可以安装带有HelloWorld模块的Nginx了
5.修改nginx.conf的内容
5.启动Nginx,在命令行输入$ curl http://localhost/hello输出hello,world就表示成功。
相关文章推荐
- 文章9:Nginx模块开发详细介绍--以HelloWorld模块为例
- 文章8:Nginx模块开发概述
- nginx模块定制开发中介入http模块的方法及NGX_HTTP_CONTENT_PHASE阶段的详细介绍
- 【Android LibGDX游戏引擎开发教程】第04期:各个模块的详细介绍
- 文章5:Linux下使用Eclipse进行Nginx 模块开发
- Nginx模块开发入门 (内容更详细)
- 【Android LibGDX游戏引擎开发教程】第04期:各个模块的详细介绍
- Nginx模块开发(1)————类helloworld
- DNN模块开发系列文章(7)——用CodeSmith Templates进行编码
- 介绍一篇关于session的好文章,写的很详细(jsp-servlet 技术)
- 介绍一篇关于session的好文章,写的很详细(jsp-servlet 技术)
- DNN模块开发系列文章(6)——DNN中的通用控件(下)
- 介绍一篇关于session的好文章,写的很详细(jsp-servlet 技术)----(转贴自JavaResearch)
- 一篇对H.323协议介绍比较详细的文章
- DNN模块开发系列文章(3)——在DNN中添加模块定义
- DNN模块开发系列文章(4)——与模块开发相关的类
- DNN模块开发系列文章(5)——DNN中的通用控件(上)
- DNN模块开发系列文章(1)——分析设计
- 介绍一篇关于session的好文章,写的很详细(jsp-servlet 技术)
- 介绍一篇关于session的好文章,写的很详细(jsp-servlet 技术)