抛去那些琐碎的对nginx的介绍,直接开始第一个nginx http的程序。
"hello world",此模块中包括get、post的处理,
1. 首先 mkdir "path"/ngx_http_hello_world
cd "path"/ngx_http_hello_workd
2. 新建文件: vi config
如下:
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_dir/ngx_http_hello_world_module.c"
3. 新建.c 文件: vi ngx_http_hello_world_module.c
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.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_HTTP_SRV_CONF|NGX_CONF_NOARGS,
ngx_http_hello_world,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_http_hello_world_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_http_hello_world_module = {
NGX_MODULE_V1,
&ngx_http_hello_world_module_ctx, /* module context */
ngx_http_hello_world_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
//URL编码 转 UTF-8,因为我这里接受到的消息体是URL编码,如果不是可以不用这个函数
void urldecode1(char *p)
{
printf("strlen(p): %d\n",(int)strlen(p));
int i=0;
while(*(p+i))
{
if ((*p=*(p+i)) == '%')
{
*p=*(p+i+1) >= 'A' ? ((*(p+i+1) & 0XDF) - 'A') + 10 : (*(p+i+1) - '0');
*p=(*p) * 16;
*p+=*(p+i+2) >= 'A' ? ((*(p+i+2) & 0XDF) - 'A') + 10 : (*(p+i+2) - '0');
i+=2;
}
else if (*(p+i)=='+')
{
*p=' ';
}
p++;
}
*p='\0';
}
//将post方法中的消息正文取出
static char *ngx_http_get_body(ngx_http_request_t *r,int length)
{
char *data_buf;
if(rb->temp_file == NULL)
{
data_buf = (char *)malloc(length+1);
ngx_chain_t* bufs = r->request_body->bufs;
ngx_buf_t* buf = NULL;
int buf_length;
int all_length = 0;
while(bufs)
{
printf("<%d>\n",__LINE__);
buf = bufs->buf;
bufs = bufs->next;
buf_length = buf->last - buf->pos;
printf("buf_length: %d\n",buf_length);
if(all_length + buf_length > length)
{
memcpy(data_buf+all_length,buf->pos,length - all_length);
all_length = length;
urldecode1((char *)buf->pos);
break;
}
memcpy(data_buf+all_length,buf->pos,buf_length);
all_length += buf_length;
}
if(all_length)
data_buf[all_length] = '\0';
}
return data_buf;
}
//正在的处理函数
static void ngx_http_hello_world_handler(ngx_http_request_t *r)
{
ngx_http_request_body_t *rb;
rb = r->request_body;
if(rb->temp_file != NULL)
{
printf("rb->temp_file != NULL\n");
while(a)
{
a = read(rb->temp_file->file.fd,data_buf,1024);
b += a;
printf("b: %d\n",b);
}
}
char *ngx_hello_world = "hello world";
char *data_buf;
ngx_buf_t *b; //返回所需
ngx_chain_t out;
if(r->method == NGX_HTTP_HEAD)
{
printf("r->method == NGX_HTTP_HEAD\n");
}
if(r->method == NGX_HTTP_GET)
{
printf("r->method == NGX_HTTP_GET\n");
}
if(r->method == NGX_HTTP_POST) //请求方法为post,则有content消息体
{
printf("r->method == NGX_HTTP_POST\n");
int length = atoi( (char*)(r->headers_in.content_length->value.data));
/*
*传输数据不超过10K,超过10k,nginx会自动post的content(消息体)存放到临时文件
*rb->temp_file->file.fd(文件描述符)
*read(rb->temp_file->file.fd,data_buf,1024); 可以循环读出来数据
*/
if(rb->temp_file == NULL)
{
data_buf = ngx_http_get_body(r,length);
urldecode1(data_buf); //url - utf-8
}
/*######################*/
/*##### 功能处理函数 ###*/
/*######################*/
}
r->headers_out.content_type.len = sizeof("text/html") - 1;
r->headers_out.content_type.data = (u_char *) "text/html"; //如果是"text/plain",在浏览器访问时会直接下载一个文件
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
out.buf = b;
out.next = NULL;
b->pos = (u_char *)ngx_hello_world; //返回的数据,这里随便给的“hello world”
b->last = (u_char *)ngx_hello_world + strlen(ngx_hello_world);
b->memory = 1;
b->last_buf = 1;
r->headers_out.status = NGX_HTTP_OK;// 发送状态码
r->headers_out.content_length_n = strlen(ngx_hello_world);// 发送内容长度
ngx_http_send_header(r);
ngx_http_output_filter(r, &out);
ngx_http_finalize_request(r, 0);
}
//调用nginx中的函数ngx_http_read_client_request_body(),
static ngx_int_t ngx_http_hello_world_urlquery_handler(ngx_http_request_t *r)
{
printf("%s() \n",__func__);
ngx_int_t rc = NGX_DONE;
rc = ngx_http_read_client_request_body(r, ngx_http_hello_world_handler); //post方法是,读取content(消息体)
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
return NGX_DONE;
}
//回调
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_urlquery_handler;
return NGX_CONF_OK;
}
自己看此代码,几个回调函数结合,并不复杂。
4. 下载nginx源码,可在官网下载,我的资源中也有,大家可以去下载
tar xvf nginx-1.6.1.tar.zxf
cd nginx-1.6.1
./configure -add-module="path"/ngx_http_hello_world --prefix="path" ( --add-module= 的意思是挂载模块,--prefix= 的意思是的可执行文件的存放目录)
make && make install
5. 修改配置文件
a. cd 到 “--prefix=”所指定的目录,有目录
b. vi conf/nginx.conf
c. 修改为
daemon off; #关闭daemon模式
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 10000; #端口
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /hello {
hello_world
}
}
}
6.cd sbin
./nginx
在浏览器输入 localhost/hello
输出: hello world
注: 结合网上很多资料,并加以注释,使更加易懂,原创,转载注明出处。