本文来自yankai0219,转载时请注明出处!http://blog.csdn.net/yankai0219/article/details/8005874
-------您的朋友 yankai0219
文章内容: 一结构体介绍
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
三、综上所述,如何安装HelloWorld模块呢?
|
1.1结构体原型
struct
ngx_command_s
{
ngx_str_t
name
;
ngx_uint_t
type
;
char
*(*
set
)(
ngx_conf_t
*cf,
ngx_command_t
*cmd,
void
*conf);
ngx_uint_t
conf
;
ngx_uint_t
offset
;
void
*
post
;
};
|
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[]={
{
ngx_string(
"hello_world"
),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_hello_world,
0,
0,
NULL
},
ngx_null_command
};
|
2.1结构体原型
struct
ngx_conf_s
{
char
*
name
;
ngx_array_t
*
args
;
ngx_cycle_t
*
cycle
;
ngx_pool_t
*
pool
;
ngx_pool_t
*
temp_pool
;
ngx_conf_file_t
*
conf_file
;
ngx_log_t
*
log
;
void
*
ctx
;
ngx_uint_t
module_type
;
ngx_uint_t
cmd_type
;
ngx_conf_handler_pt
handler
;
char
*
handler_conf
;
};
|
3.1结构体原型
typedef
struct
{
ngx_int_t
(*
preconfiguration
)(
ngx_conf_t
*cf);//在读入配置文件前调用
ngx_int_t
(*
postconfiguration
)(
ngx_conf_t
*cf);//在读入配置文件后调用
void
*(*
create_main_conf
)(
ngx_conf_t
*cf);//在创建全局部分配置时调用(比如,用来分配空间和设置默认值)
char
*(*
init_main_conf
)(
ngx_conf_t
*cf,
void
*conf);//
在初始化全局部分的配置时调用(比如,把原来的默认值用nginx.conf 读到的值来覆盖)
void
*(*
create_srv_conf
)(
ngx_conf_t
*cf);//在创建主机部分的配置时调用
char
*(*
merge_srv_conf
)(
ngx_conf_t
*cf,
void
*prev,
void
*conf);//与全局部分配置合并时调用
void
*(*
create_loc_conf
)(
ngx_conf_t
*cf);//创建位置部分的配置时掉用
char
*(*
merge_loc_conf
)(
ngx_conf_t
*cf,
void
*prev,
void
*conf);//与主机部分配置合并时调用
}
ngx_http_module_t
;
|
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={
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
|
4.1结构体原型
struct
ngx_module_s
{
ngx_uint_t
ctx_index
;
ngx_uint_t
index
;
ngx_uint_t
spare0
;
ngx_uint_t
spare1
;
ngx_uint_t
spare2
;
ngx_uint_t
spare3
;
ngx_uint_t
version
;
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 */
uintptr_t
spare_hook0
;
uintptr_t
spare_hook1
;
uintptr_t
spare_hook2
;
uintptr_t
spare_hook3
;
uintptr_t
spare_hook4
;
uintptr_t
spare_hook5
;
uintptr_t
spare_hook6
;
uintptr_t
spare_hook7
;
};
|
4.2结构体作用: 这个结构体变量名为为ngx_http_<module_name>_module。 它包含模块的主要内容和指令的执行部分,也有一些回调函数(退出线程,推退出进程等等)。这些函数的定义是把数据处理关联到特定模块的关键。 在进程/线程退出的时候,模块可以添加一些回调函数来运行,但大多数模块用不到。 |
4.3实例: 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;
}
|
struct
ngx_http_request_s
{
uint32_t
signature
;
/* "HTTP" */
ngx_connection_t
*
connection
;
void
**
ctx
;
void
**
main_conf
;
void
**
srv_conf
;
void
**
loc_conf
;
ngx_http_event_handler_pt
read_event_handler
;
ngx_http_event_handler_pt
write_event_handler
;
#if
(NGX_HTTP_CACHE)
ngx_http_cache_t
*
cache
;
#endif
ngx_http_upstream_t
*
upstream
;
ngx_array_t
*
upstream_states
;
/* of ngx_http_upstream_state_t */
ngx_pool_t
*
pool
;
ngx_buf_t
*
header_in
;
ngx_http_headers_in_t
headers_in
;
ngx_http_headers_out_t
headers_out
;
ngx_http_request_body_t
*
request_body
;
time_t
lingering_time
;
time_t
start_sec
;
ngx_msec_t
start_msec
;
ngx_uint_t
method
;
ngx_uint_t
http_version
;
ngx_str_t
request_line
;
ngx_str_t
uri
;
ngx_str_t
args
;
ngx_str_t
exten
;
ngx_str_t
unparsed_uri
;
ngx_str_t
method_name
;
ngx_str_t
http_protocol
;
ngx_chain_t
*
out
;
ngx_http_request_t
*
main
;
ngx_http_request_t
*
parent
;
ngx_http_postponed_request_t
*
postponed
;
ngx_http_post_subrequest_t
*
post_subrequest
;
ngx_http_posted_request_t
*
posted_requests
;
ngx_http_virtual_names_t
*
virtual_names
;
ngx_int_t
phase_handler
;
ngx_http_handler_pt
content_handler
;
ngx_uint_t
access_code
;
ngx_http_variable_value_t
*
variables
;
#if
(NGX_PCRE)
ngx_uint_t
ncaptures
;
int
*
captures
;
u_char
*
captures_data
;
#endif
size_t
limit_rate
;
/* used to learn the Apache compatible response length without a header */
size_t
header_size
;
off_t
request_length
;
ngx_uint_t
err_status
;
ngx_http_connection_t
*
http_connection
;
ngx_http_log_handler_pt
log_handler
;
ngx_http_cleanup_t
*
cleanup
;
unsigned
subrequests
:8;
unsigned
count
:8;
unsigned
blocked
:8;
unsigned
aio
:1;
unsigned
http_state
:4;
/* URI with "/." and on Win32 with "//" */
unsigned
complex_uri
:1;
/* URI with "%" */
unsigned
quoted_uri
:1;
/* URI with "+" */
unsigned
plus_in_uri
:1;
/* URI with " " */
unsigned
space_in_uri
:1;
unsigned
invalid_header
:1;
unsigned
add_uri_to_alias
:1;
unsigned
valid_location
:1;
unsigned
valid_unparsed_uri
:1;
unsigned
uri_changed
:1;
unsigned
uri_changes
:4;
unsigned
request_body_in_single_buf
:1;
unsigned
request_body_in_file_only
:1;
unsigned
request_body_in_persistent_file
:1;
unsigned
request_body_in_clean_file
:1;
unsigned
request_body_file_group_access
:1;
unsigned
request_body_file_log_level
:3;
unsigned
subrequest_in_memory
:1;
unsigned
waited
:1;
#if
(NGX_HTTP_CACHE)
unsigned
cached
:1;
#endif
#if
(NGX_HTTP_GZIP)
unsigned
gzip_tested
:1;
unsigned
gzip_ok
:1;
unsigned
gzip_vary
:1;
#endif
unsigned
proxy
:1;
unsigned
bypass_cache
:1;
unsigned
no_cache
:1;
/*
* instead of using the request context data in
* ngx_http_limit_conn_module and ngx_http_limit_req_module
* we use the single bits in the request structure
*/
unsigned
limit_conn_set
:1;
unsigned
limit_req_set
:1;
#if
0
unsigned
cacheable:1;
#endif
unsigned
pipeline
:1;
unsigned
plain_http
:1;
unsigned
chunked
:1;
unsigned
header_only
:1;
unsigned
keepalive
:1;
unsigned
lingering_close
:1;
unsigned
discard_body
:1;
unsigned
internal
:1;
unsigned
error_page
:1;
unsigned
ignore_content_encoding
:1;
unsigned
filter_finalize
:1;
unsigned
post_action
:1;
unsigned
request_complete
:1;
unsigned
request_output
:1;
unsigned
header_sent
:1;
unsigned
expect_tested
:1;
unsigned
root_tested
:1;
unsigned
done
:1;
unsigned
logged
:1;
unsigned
buffered
:4;
unsigned
main_filter_need_in_memory
:1;
unsigned
filter_need_in_memory
:1;
unsigned
filter_need_temporary
:1;
unsigned
allow_ranges
:1;
#if
(NGX_STAT_STUB)
unsigned
stat_reading
:1;
unsigned
stat_writing
:1;
#endif
/* used to parse HTTP headers */
ngx_uint_t
state
;
ngx_uint_t
header_hash
;
ngx_uint_t
lowcase_index
;
u_char
lowcase_header
[NGX_HTTP_LC_HEADER_LEN];
u_char
*
header_name_start
;
u_char
*
header_name_end
;
u_char
*
header_start
;
u_char
*
header_end
;
/*
* a memory that can be reused after parsing a request line
* via ngx_http_ephemeral_t
*/
u_char
*
uri_start
;
u_char
*
uri_end
;
u_char
*
uri_ext
;
u_char
*
args_start
;
u_char
*
request_start
;
u_char
*
request_end
;
u_char
*
method_end
;
u_char
*
schema_start
;
u_char
*
schema_end
;
u_char
*
host_start
;
u_char
*
host_end
;
u_char
*
port_start
;
u_char
*
port_end
;
unsigned
http_minor
:16;
unsigned
http_major
:16;
};
|
结构体成员变量说明: 1)uri:请求路径,比如:“/query.cgi” 2) args:是在问号之后请求的参数,比如:“name=john” 3)headers_in有很多有用的东西,如cookie和浏览器信息。 |
typedef
struct
{
ngx_list_t
headers
;
ngx_uint_t
status
;
ngx_str_t
status_line
;
ngx_table_elt_t
*
server
;
ngx_table_elt_t
*
date
;
ngx_table_elt_t
*
content_length
;
ngx_table_elt_t
*
content_encoding
;
ngx_table_elt_t
*
location
;
ngx_table_elt_t
*
refresh
;
ngx_table_elt_t
*
last_modified
;
ngx_table_elt_t
*
content_range
;
ngx_table_elt_t
*
accept_ranges
;
ngx_table_elt_t
*
www_authenticate
;
ngx_table_elt_t
*
expires
;
ngx_table_elt_t
*
etag
;
ngx_str_t
*
override_charset
;
size_t
content_type_len
;
ngx_str_t
content_type
;
ngx_str_t
charset
;
u_char
*
content_type_lowcase
;
ngx_uint_t
content_type_hash
;
ngx_array_t
cache_control
;
off_t
content_length_n
;
time_t
date_time
;
time_t
last_modified_time
;
}
ngx_http_headers_out_t
;
|
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = 100;
r->headers_out.content_type.len = sizeof("image/gif") - 1;
r->headers_out.content_type.data = (u_char *) "image/gif";
ngx_http_send_header(r);
|
r->headers_out.content_encoding = ngx_list_push(&r-
>headers_out.headers);
if (r->headers_out.content_encoding == NULL) {
return NGX_ERROR;
}
r->headers_out.content_encoding->hash = 1;
r->headers_out.content_encoding->key.len = sizeof("Content-
Encoding") - 1;
r->headers_out.content_encoding->key.data = (u_char *) "Content-
Encoding";
r->headers_out.content_encoding->value.len = sizeof("deflate") -
1;
r->headers_out.content_encoding->value.data = (u_char *)
"deflate";
ngx_http_send_header(r);
|
ngx_buf_t *b;
ngx_chain_t out;
|
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (b == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"Failed to allocate response buffer.");
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
b->pos = some_bytes; /* first position in memory of the data */
b->last = some_bytes + some_bytes_length; /* last position */
b->memory = 1; /* content is in read-only memory */
/* (i.e., filters should copy it rather than rewrite in place) */
b->last_buf = 1; /* there will be no more buffers in the request
*/
|
out.buf = b;
out.next = NULL;
|
return ngx_http_output_filter(r, &out);
|
static
ngx_int_t ngx_http_hello_world_handler(
ngx_http_request_t
*r)
{
ngx_buf_t
*b;
ngx_chain_t
out;
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.
buf
=b;
out.
next
=NULL;
b->
pos
=ngx_hello_world;
b->
last
=ngx_hello_world+
sizeof
(ngx_hello_world);
b->
memory
=1;
b->
last_buf
=1;
r->
headers_out
.
status
=NGX_HTTP_OK;
r->
headers_out
.
content_length_n
=
sizeof
(ngx_hello_world);
ngx_http_send_header(r);
return
ngx_http_output_filter(r,&out);
}
|
#include
<ngx_config.h>
#include
<ngx_core.h>
#include
<ngx_http.h>
#include
<ngx_buf.h>
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_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_hello_world,
0,
0,
NULL
},
ngx_null_command
};
static
u_char
ngx_hello_world[]=
"hello world"
;
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
ngx_int_t ngx_http_hello_world_handler(
ngx_http_request_t
*r)
{
ngx_buf_t
*b;
ngx_chain_t
out;
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.
buf
=b;
out.
next
=NULL;
b->
pos
=ngx_hello_world;
b->
last
=ngx_hello_world+
sizeof
(ngx_hello_world);
b->
memory
=1;
b->
last_buf
=1;
r->
headers_out
.
status
=NGX_HTTP_OK;
r->
headers_out
.
content_length_n
=
sizeof
(ngx_hello_world);
ngx_http_send_header(r);
return
ngx_http_output_filter(r,&out);
}
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_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请求进行处理。
|
1.下载Nginx最新代码2.建立模块目录与代码3.创建Makefile文件4.直接$make && make install就可以安装带有HelloWorld模块的Nginx了5.修改nginx.conf的内容5.启动Nginx,在命令行输入$ curl http://localhost/hello输出hello,world就表示成功。