首页 > 代码库 > nginx 学习(二) hello world 程序
nginx 学习(二) hello world 程序
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); }
nginx 学习(二) hello world 程序