Nginx模块开发教程之Hello world

date: 2017.02.20; modification:2017.02.21

目录:

1 概述

不管是google搜索Nginx模块开发教程, 还是各个教程中的参考资料, 很多都指向了这篇文章: Emiller's Guide To Nginx Module Development, 这篇文章的细节描述不少, 但是作为入门材料不够简洁, 无法简单快速给予读者一个关于模块编写整体的概念, 所以不是很适合作为最基础的入门文章. 所以本文便提供一个能编能跑的Hello world例子.

本文代码在如下环境上测试编译运行通过.

要了解如何开发Nginx模块, 需要先对Nginx的整体框架以及Nginx模块有个基本的概念, 可以参见: Nginx架构介绍

2 Hello world模块程序

一般对于c语言实现的模块, 不外乎做这么一件事: 编写一个主程序可识别的模块入口(一般是个入口结构体或函数), 并将这个入口注册给主程序.

Nginx实现该机制的做法是通过编译配置文件. 一个Nginx的Hello world模块的最小组成, 包括2个部分:

config文件(文件名就叫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"
    

这份源码配置很简单, 顾名思义也可以了解个大概:

而这个入口, 便是整个模块最关键的一步, 整个模块都是由该入口展开的. 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_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,                          /* 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
};


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_module_t ngx_http_hello_world_module便是上面说的入口. 其中:

2.1 编译运行

上面的config与.c文件, 需要放在同一个文件夹中: 比如叫做: ngx_http_hello_world_module.

编译:

    
./configure --with-http_ssl_module \
    --prefix=./usr \
    --add-module=module/ngx_http_hello_world_module/ \
    || exit 1

make install

配置:

在主配置文件nginx.conf中, 加入如下内容:

location = /hello {
  hello_world;
}

在代码放在与原有location同级并列的位置即可.

运行:

./usr/sbin/nginx -c $PWD/usr/conf/nginx.conf # 修改为自己的配置文件.

然后浏览器访问:

http://localhost/hello

即可看到返回的"Hello world".

3 参考:

http://nutrun.com/weblog/2009/08/15/hello-world-nginx-module.html

http://www.evanmiller.org/nginx-modules-guide.html

http://www.oschina.net/translate/nginx-modules-guide?cmp