hello wrold
1 本节目的
2实现步骤
2.1config编写
2.2模块代码实现
2.3配置文件的编写
3将模块编译进nginx中
1本节的目的
本节用nginx来实现一个经典程序hello world,这个程序也是我们学任何编程语言时首先接触的程序,这个程序的目的是
初步了解nginx怎样嵌入第三方模块,也是学习nginx的HTTP模块的入门。
2实现步骤
nginx 提供了一种简单的方式将第三方模块嵌入nginx中:只需要三个步骤
步骤一:编写config
步骤二:实现模块的代码
步骤三:修改配置参数,将第三方模块编译到nginx中
下面我们来用最简单的hello world实例来讲这三个步骤的实现。
2.1config编写
config文件里面包含了三个参数,这三个参数如下:
ngx_addon_name:第三方模块名字,这个好像用处不大,一般设置为模块名称
HTTP_MODULES:HTPP模块名称
NGX_ADDON_SRCS:第三方模块源代码路径
下面是helloworld程序的config:
ngx_add_name=ngx_http_hello_module
HTTP_MODULES="$HTTP_MODULES ngx_http_hello_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_module.c"
2.2模块代码实现
下面来看怎样实现ngx_http_hello_module.c。
首先我们要定义两个函数:
static char* ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r);
ngx_http_hello
这个函数使用来分析配置文件中的参数,因为我们仅仅要输出hello world 所以我们用无参数的配置,即不许要解析参数的值,下一节我会详细将怎样分析配置参数
ngx_http_hello_handler
每个模块都有一个handler函数,这个函数负责对来自客户端请求的真正处理。这个函数的处理,既可以选择自己直接生成内容,也可以选择拒绝处理,由后续的handler去进行处理,或者是选择丢给后续的filter进行处理。
然后我们要定义三个结构体,这三个结构体是每个模块必不可缺少的结构体:
模块配置指令结构体:
static ngx_command_t ngx_http_hello_commands[] = {
{
ngx_string("test_hello"),
NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS,
ngx_http_hello,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
ngx_null_command
};
模块上下文结构体:
static ngx_http_module_t ngx_http_hello_module_ctx = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
模块的定义结构体:
ngx_module_t ngx_http_hello_module = {
NGX_MODULE_V1,
&ngx_http_hello_module_ctx,
ngx_http_hello_commands,
NGX_HTTP_MODULE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NGX_MODULE_V1_PADDING
};
这里我们仅仅知道这三个结构体就行,后面我们会详细介绍。
然后看看nginx函数的实现:
static char* ngx_http_hello(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_handler;
return NGX_CONF_OK;
}
这个函数主要是解析配置的参数,也可以设置模块的handler函数,这里我们没有解析配置参数,仅仅加载模块的handler函数。
再看真正处理用户请求的handler函数:
static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r)
{
if (!(r->method & (NGX_HTTP_HEAD | NGX_HTTP_GET)))
{
return NGX_HTTP_NOT_ALLOWED;
}
ngx_int_t rc = ngx_http_discard_request_body(r);
if (rc != NGX_OK)
{
return rc;
}
ngx_str_t type = ngx_string("text/html");
ngx_str_t response = ngx_string("hello world!");
r->headers_out.content_type = type;
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = response.len;
if (r->method == NGX_HTTP_HEAD)
{
return ngx_http_send_header(r);
}
ngx_buf_t* buf = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (buf == NULL)
{
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
buf->pos = ngx_pcalloc(r->pool, response.len);
buf->last = buf->pos + response.len;
buf->last_buf = 1;
buf->memory = 1;
ngx_memcpy(buf->pos, response.data, response.len);
ngx_chain_t out;
out.buf = buf;
out.next = NULL;
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
{
return rc;
}
return ngx_http_output_filter(r, &out);
}
这个函数才是真正处理用户请求的函数,它在解析配置参数以后根据用户的请求作出相应处理,并把处理结果返回给用户。
这样一个简单的hello模块的代码就基本上完成了,其实主要就是上面的三个结构体的定义和handler函数的实现。
2.3配置文件的编写
我们实现一个功能是当我们在浏览其中输入:localhost/hello 按回车键时会看到:hello world!
在配置中应该有hello并且写在nginx.conf 的location:
location /hello {
test_hello ;//无参数的配置
}
3将模块编译进nginx中
即安装第三方模块,如下:
./configure --prefix=/home/smtl/桌面/testNx/nginx \
--with-http_ssl_module \
--with-pcre=/home/smtl/下载/pcre-8.33 \
--with-zlib=/home/smtl/下载/zlib-1.2.8 \
--with-openssl=/home/smtl/下载/openssl-0.9.8o \
<span style="color:#FF0000;">--add-module=/home/smtl/桌面/testNx/nginx-1.0.15/my_hello_module</span>
(make , make install)注意我们编写的代码所放的文件要放在和nginx源码所放的目录相同:nginx源码放在那个文件里,我们编写的代码的文件就放在那个文件里。
红色标记的部分是我们编写的代码ngx_htttp_hello_module.c所在的文件夹。
然后在浏览器里面输入:localhost/hello。
浏览器输出hello world
程序源代码:
#include <ngx_config.h>
#include <ngx_http.h>
#include <ngx_core.h>
static char* ngx_http_hello(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r);
static ngx_command_t ngx_http_hello_commands[] = {
{
ngx_string("test_hello"),
NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS,
ngx_http_hello,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
ngx_null_command
};
static ngx_http_module_t ngx_http_hello_module_ctx = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
/* static 加上static有错误 */
ngx_module_t ngx_http_hello_module = {
NGX_MODULE_V1,
&ngx_http_hello_module_ctx,
ngx_http_hello_commands,
NGX_HTTP_MODULE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NGX_MODULE_V1_PADDING
};
static char* ngx_http_hello(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_handler;
return NGX_CONF_OK;
}
static ngx_int_t ngx_http_hello_handler(ngx_http_request_t *r)
{
if (!(r->method & (NGX_HTTP_HEAD | NGX_HTTP_GET)))
{
return NGX_HTTP_NOT_ALLOWED;
}
ngx_int_t rc = ngx_http_discard_request_body(r);
if (rc != NGX_OK)
{
return rc;
}
ngx_str_t type = ngx_string("text/html");
ngx_str_t response = ngx_string("hello world!");
r->headers_out.content_type = type;
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = response.len;
if (r->method == NGX_HTTP_HEAD)
{
return ngx_http_send_header(r);
}
ngx_buf_t* buf = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (buf == NULL)
{
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
buf->pos = ngx_pcalloc(r->pool, response.len);
buf->last = buf->pos + response.len;
buf->last_buf = 1;
buf->memory = 1;
ngx_memcpy(buf->pos, response.data, response.len);
ngx_chain_t out;
out.buf = buf;
out.next = NULL;
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
{
return rc;
}
return ngx_http_output_filter(r, &out);
}
http://blog.youkuaiyun.com/xiaoliangsky/article/details/39254481
work hard!!!!!