摘要:上一节介绍了Nginx模块开发的基础知识,本节将以一个完整的示例讲解如何实现一个最简单的hello world模块,本模块将实现用户访问http://localhost/时在浏览器上显示一个Hello world字符串功能。
1、http模块常用函数介绍
ngx_http_discard_request_body()
ngx_http_send_header()
ngx_create_temp_buf()
ngx_http_output_filter()
2、配置文件
worker_processes 2;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
location / {
}
}
}
3、模块完整代码
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r);
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"), // 当nginx.conf中出现hello_world字段时就会调用该模块,例如:location / { hello_world; }
// 下面配置分别表示可以出现在nginx.conf的全局配置、server配置、location配置和limit_except中
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | \
NGX_CONF_NOARGS, // 配置项不允许带参数
ngx_http_hello_world, // 配置处理函数,set回调函数
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
ngx_null_command // 结构体结尾标志
};
static ngx_http_module_t ngx_http_hello_world_module_ctx = { //模块上下文结构,HTTP框架要求,固定用法
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, // http模块
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);
// http框架在处理用户请求进行到NGX_HTTP_CONTENT_PHASE阶段,如果请求的主机域名,URL和hello_world相匹配
// 那么就调用这handler指向的方法ngx_http_hello_world_handler
clcf->handler = ngx_http_hello_world_handler;
return NGX_CONF_OK;
}
static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r)
{
ngx_chain_t out; // 发送的响应体链表
ngx_buf_t *b; // 响应体链表节点的内容
ngx_str_t type = ngx_string("text/plain"); // 告诉客户端如何发送的是文本类型
ngx_str_t response = ngx_string("Hello World"); // 要发送的字符串
ngx_int_t rc = ngx_http_discard_request_body(r); // 将接收自客户端的HTTP包体丢弃掉,不能不处理,否则用户端请求超时
if (rc != NGX_OK) {
return rc;
}
r->headers_out.status = NGX_HTTP_OK; // http响应码200
r->headers_out.content_length_n = response.len; // 响应体长度
r->headers_out.content_type = type; // 响应体类型,文本类型
rc = ngx_http_send_header(r); // 发送头部
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
return rc;
}
b = ngx_create_temp_buf(r->pool, response.len); // 异步发送,要用堆内存空间
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_memcpy(b->pos, response.data, response.len);
b->last = b->pos + response.len; // 发送内容结束位置
b->last_buf = 1; // 等于1表示最后一个字段
out.buf = b; // 第一串内容
out.next = NULL; // 只发送一串内容
return ngx_http_output_filter(r, &out); //传递至其它过滤器处理
}
4、编译运行
./configure --perfix=/usr/local/nginx # 配置
make # 编译
make install # 安装
/usr/local/nginx/sbin/nginx # 运行
5、测试
curl -i http://localhost/