手把手教你开发Nginx模块

合集下载

Nginx开发和配置教程

Nginx开发和配置教程

Nginx开发和配置教程一、Nginx的开发1. Nginx模块开发-编写模块的配置指令:模块的配置指令决定了模块如何被配置和使用。

-实现模块的处理函数:处理函数负责处理来自客户端的请求并返回响应。

- 注册模块:将模块注册到Nginx的配置中。

2. Nginx的事件驱动模型-事件模块:负责监听和接收客户端请求。

-连接池:管理与客户端的连接。

-请求处理:负责处理客户端的请求并返回响应。

二、Nginx的配置1. Nginx配置文件2. Nginx的基本配置指令- worker_processes:指定Nginx的工作进程数,用于处理并发请求。

- pid:指定Nginx的进程ID文件路径。

- error_log:指定错误日志文件的路径。

- access_log:指定访问日志文件的路径。

- events:指定Nginx的事件模块配置。

3. Nginx的虚拟主机配置- server:定义一个虚拟主机。

- listen:指定虚拟主机监听的端口。

- server_name:指定虚拟主机的域名。

- root:指定虚拟主机的根目录。

4. Nginx的负载均衡配置- upstream:定义一个负载均衡服务器组。

- server:定义一个后端服务器。

- weight:指定后端服务器的权重,用于分配请求。

- ip_hash:根据客户端IP地址进行负载均衡。

总结:本文介绍了Nginx的开发和配置教程。

在Nginx的开发方面,我们了解了Nginx的模块开发和事件驱动模型。

在Nginx的配置方面,我们了解了Nginx的配置文件,基本配置指令,虚拟主机配置和负载均衡配置。

希望这些内容能帮助您更好地开发和配置Nginx服务器。

Nginx源码分析--模块module解析执行nginx.conf配置文件流程分析一

Nginx源码分析--模块module解析执行nginx.conf配置文件流程分析一

Nginx源码分析--模块module解析执⾏nginx.conf配置⽂件流程分析⼀ 搭建nginx服务器时,主要的配置⽂件 nginx.conf 是部署和维护服务器⼈员经常要使⽤到的⽂件,⾥⾯进⾏了许多服务器参数的设置。

那么nginx 以模块 module为⾻架的设计下是如何运⽤模块 module来解析并执⾏nginx.conf配置⽂件下的指令的呢?在探究源码之前,需要对nginx下的模块 module 有个基本的认知(详情参考前⾯的博⽂ )同时也要对nginx中常⽤到的⼀些结构有个基本的了解如:内存池pool 管理相关的函数、ngx_string 的基本结构等(详情参考前⾯的博⽂),若不然看代码的时候可能不能很明晰其中的意思,本⽂着重探究的是解析执⾏的流程。

1、从main函数说起。

Nginx的main函数在nginx.c⽂件中(本⽂使⽤release-1.3.0版本源码,200⾏),因为是主函数其中涉及到了许许多多的功能模块的初始化等内容,我们只关注我们需要的部分。

看到326⾏:ngx_max_module = 0;for (i = 0; ngx_modules[i]; i++) {ngx_modules[i]->index = ngx_max_module++;} cycle = ngx_init_cycle(&init_cycle); 可以看出来,这⾥对 ngx_modules (中有介绍)进⾏了索引编号,并且计算得到模块的总数 ngx_max_module。

然后,对cycle进⾏初始化,跳转到 ngx_init_cycle中。

对于cycle 这个变量是nginx的核⼼变量,可以说模块机制都是围绕它进⾏的,⾥⾯的参数⽐较复杂涉及到的内容⼗分多,本⽂并不详细对它讨论,可以将其看作是⼀个核⼼资源库。

2、ngx_init_cycle 函数 这个函数在⽂件ngx_cycle.c中(43⾏),这个函数是nginx初始化中最重要的函数之⼀,⾥⾯涉及到与cycle变量相关的初始化⼯作,看到第188⾏cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module *sizeof(void *)); 这⾥获取了 ngx_max_module 个指针空间,⽤来保存每个模块的配置信息,从cycle 变量的字段conf_ctx 命名中就可以知道,ctx 为context 上下⽂的缩写。

nginx模块开发

nginx模块开发
nginx模块开发
By 薛长俊 2013-11
Nginx模块开发
模块化 daemon 编码规范
模块化
• 模块分类
handlers,处理http请求并构造输出 filters,处理handler产生的输出 load-balancers,当有多于一个的后端服务器时,选择一台将http请求发 送过去
模块化
daemon
• 编写Handler
Nginx允许handler一次产生一组输出,可以产生多次,Nginx将输出组织成一 个单链表结构,链表中的每个节点是一个chain_t。
daemon
• 组合Nginx Module
一个Nginx模块被定义为一个ngx_module_t结构,这个结构的字段很多,不 过开头和结尾若干字段一般可以通过Nginx内置的宏去填充,下面是我们 echo模块的模块主体定义:
模块化
• ngx_module_t,ngx_module_s
ngx_uint_t type; //用于区分core、event、http和mail。 ngx_int_t (*init_master)(ngx_log_t *log); //初始化master时执行 ngx_int_t (*init_module)(ngx_cycle_t *cycle); //初始化module时执行 ngx_int_t (*init_process)(ngx_cycle_t *cycle); //初始化process时执行 ngx_int_t (*init_thread)(ngx_cycle_t *cycle); //初始化thread时执行 void (*exit_thread)(ngx_cycle_t *cycle); //退出thread时执行 void (*exit_process)(ngx_cycle_t *cycle); //退出process时执行 void (*exit_master)(ngx_cycle_t *cycle); //退出master时执行 ....

nginx详细配置

nginx详细配置

nginx详细配置Nginx内容概览1、nginx简介(1)介绍 nginx的应⽤场景和具体可以做什么事情(2)介绍什么是反向代理(3)介绍什么是负载均衡(4)介绍什么是动静分离2、nginx安装(1)介绍 nginx在 linux系统中如何进⾏安装3、nginx常⽤的命令和配置⽂件(1)介绍 nginx启动、关闭、重新加载命令(2)介绍 nginx的配置⽂件4、nginx配置实例-反向代理5、nginx配置实例-负载均衡6、nginx配置实例-动静分离7、nginx原理与优化参数配置8、搭建 nginx⾼可⽤集群(1)搭建 nginx⾼可⽤集群(主从模式)(2)搭建 nginx⾼可⽤集群(双主模式)第 1 章 Nginx 简介1.1 Nginx 概述Nginx ("engine x") 是⼀个⾼性能的 HTTP 和反向代理服务器,特点是占有内存少,并发能⼒强,事实上 nginx的并发能⼒确实在同类型的⽹页服务器中表现较好,中国⼤陆使⽤ nginx⽹站⽤户有:百度、京东、新浪、⽹易、腾讯、淘宝等1.2 Nginx 作为 web 服务器Nginx 可以作为静态页⾯的 web 服务器,同时还⽀持 CGI 协议的动态语⾔,⽐如 perl、php等。

但是不⽀持 java。

Java程序只能通过与tomcat配合完成。

Nginx专为性能优化⽽开发,性能是其最重要的考量,实现上⾮常注重效率,能经受⾼负载的考验,有报告表明能⽀持⾼达50,000个并发连接数。

1.3 正向代理Nginx 不仅可以做反向代理,实现负载均衡。

还能⽤作正向代理来进⾏上⽹等功能。

正向代理:如果把局域⽹外的 Internet 想象成⼀个巨⼤的资源库,则局域⽹中的客户端要访问Internet,则需要通过代理服务器来访问,这种代理服务就称为正向代理。

1.4 反向代理反向代理,其实客户端对代理是⽆感知的,因为客户端不需要任何配置就可以访问,我们只需要将请求发送到反向代理服务器,由反向代理服务器去选择⽬标服务器获取数据后,在返回给客户端,此时反向代理服务器和⽬标服务器对外就是⼀个服务器,暴露的是代理服务器地址,隐藏了真实服务器 IP地址。

Nginx模块开发文档

Nginx模块开发文档

nginx文档吴东April 28, 2009Contents1前言52基本配置72.1安装 (7)2.2配置说明 (10)2.3启动和控制 (25)3深入源码273.1源码结构 (27)3.2configure配置 (27)3.3nginx源码习惯 (27)3.4常用基础库 (28)3.5core模块 (40)3.6event模块 (44)3.7http模块 (46)4模块编写554.1http模块编写 (55)4.2基于nginx的高性能服务器开发. . . . . . . . . 555附录575.1编译器参数 (57)5.2系统函数 (59)CONTENTS CONTENTSChapter 1前言在互联网编程中,http服务器编程作为一个非常重要方向一直为各种语言所重视,从c语言的apache,Lighttpd到当前非常流行的nginx。

Java有tom-cat,jetty,websphere等众多服务器,pyhoen的zope等服务器。

既有重量级的服务器,又有轻量级的,嵌入式的服务器。

从互联网的应用来说,c语言的http 服务器一直占有主导地位,当前最流行的三个开源服务器有apache,Lighttpd和nginx。

Apache作为经典的Web服务器,除了慢没有别的缺点了,Apache2对fcgi支持并不好,非常好用的proxy和proxy_ajp (很多人用它作为tomcat的前端),不支持epoll(这年头,epoll几乎是性能的必备)。

Lighttpd作为杀手级的静态文件能力,杀手级的fcgi能力但是proxy模块不够稳定。

Nginx速度快,占用资源少,杀手级的proxy和rewrite,非常不错的静态文件能力,最适合作为整个网站的前端服务(将php、svn等不同请求发送往后端apache)。

现在国内Nginx的用户越来越多了,多数拥抱Nginx的网站都钟意其优异的性能表现,如果是相对比较大的网站,节约下来的服务器成本无疑是客观的。

nginx模块开发指南(中文)

nginx模块开发指南(中文)

Emiller的Nginx模块开发指南作者:Evan Miller草稿: 2009年8月13日译者:姚伟斌 草稿:2009年9月21日内容目录0. 预备知识 (1)1. Nginx模块任务委派的主要轮廓 (1)2. Nginx模块的组成 (3)2.1. 模块的配置结构体 (3)2.2. 模块的指令 (4)2.3. 模块的上下文 (6)2.3.1. 创建位置结构体(create_loc_conf) (8)2.3.2. 初始化结构体(merge_loc_conf) (8)2.4. 模块定义 (9)2.5. 模块注册 (10)3. 处理模块、过滤模块和 负载均衡模块 (10)3.1. 剖析处理模块(非代理) (10)3.1.1. 获得位置配置结构体 (10)3.1.2. 产生回复 (11)3.1.3. 发送HTTP头部 (12)3.1.4. 发送HTTP主体 (13)3.2. 上游模块剖析(又称代理模块) (14)3.2.1.代理模块回调函数的概要 (14)3.2.2. create_request 回调函数 (16)3.2.3. process_header 回调函数 (17)3.2.4. 状态保持 (18)3.3.处理模块的注册 (19)4 过滤模块 (19)4.1. 剖析头部过滤函数 (19)4.2. 剖析主体过滤函数 (20)4.3 过滤函数的注册 (22)5. 剖析负载均衡模块 (24)5.1.激活指令 (24)5.2.注册函数 (25)5.3.上游主机初始化函数 (27)5.4.同伴初始化函数 (28)5.5.负载均衡函数 (30)5.6. 同伴释放函数 (31)6. 完成并编译自定义模块 (32)7.高级话题 (33)中文版本修改日志 (33)翻译说明:在nginx的模块编写过程中,时常苦于文档的不足,而源代码中又没多少注释。

只有Emiller的这篇英文文档带我入门,在自己研读的过程中,就想将其翻译出来,让其他人能快速的浏览,但是如果你想更深入的进入nginx的代码开发,最好是多读nginx的代码。

Nginx模块开发手册

Nginx模块开发手册

1. 预备知识你应当比较熟悉C语言。

不光是“C-语法",你起码还得知道结构体和预处理指令,同时保证看到指针和函数引用出现时心里不会发毛。

否则的话,就算信春哥也是没用的,看看K&R吧。

你得对HTTP协议有一定的了解,毕竟你是在和一个web server打交道。

如果你熟悉Nginx的配置文件就太好不过了。

如果不熟悉,也没关系,这里简单介绍一下,知道概念先:Nginx配置文件主要分成四部分:main(全局设置)、server(主机设置)、upstream(上游服务器设置)和location(URL匹配特定位置后的设置)。

每部分包含若干个指令。

main部分设置的指令将影响其它所有设置;server部分的指令主要用于指定主机和端口;upstream的指令用于设置一系列的后端服务器;location部分用于匹配网页位置(比如,根目录“/”,“/images”,等等)。

他们之间的关系式:server继承main,location继承server;upstream既不会继承指令也不会被继承。

它有自己的特殊指令,不需要在其他地方的应用。

在下面很多地方都会涉及这四个部分,切记。

好了,让我们开始吧。

2. Nginx模块委派概述Nginx的模块有三种角色:* handlers 处理http请求并构造输出* filters 处理handler产生的输出* load-balancers 当有多于一个的后端服务器时,选择一台将http请求发送过去许多可能你认为是web server的工作,实际上都是由模块来完成的:任何时候,Nginx提供文件或者转发请求到另一个server,都是通过handler来实现的;而当需要Nginx用gzip压缩输出或者在服务端加一些东东的话,filter就派上用场了;Nginx的core模块主要管理网络层和应用层协议,并启动针对特定请求的一系列后续模块。

这种分散式的体系结构使得由你自己来实现强大的内部单元成为了可能。

Emiller的nginx模块开发指引

Emiller的nginx模块开发指引

要非常感谢nginx,它帮助我更加了解蝙蝠侠这个喜剧角色。

蝙蝠侠很快,nginx也很快。

蝙蝠侠在与罪恶斗争,nginx在与浪费CPU、内存泄漏等现象做斗争。

蝙蝠侠在压力下能保持良好状态,nginx在强大的服务请求压力下表现出色。

但是,蝙蝠侠如果没有那根蝙蝠侠万能腰带(batman utility belt),那他就什么都不是。

在任何时候,蝙蝠侠的万能腰带都应该包括一个锁扣、几个batarang(蝙蝠侠的特殊武器)、几个bat-cuff(护腕)、夜视眼镜、bat-tracer(跟踪器?)、几个bat-darts(蝙蝠镖)...或者还包括一个apple iphone。

当蝙蝠侠需要使他的敌人失明、失聪、或者晕倒,或者当他需要跟踪他的敌人,或者给他的敌人发个短信,你最好相信他正在他的万能腰带上找一个合适的工具。

这根腰带对蝙蝠侠的行动如此至关重要,所以,当蝙蝠侠在选择穿裤子还是穿腰带的时候,他肯定会选择穿腰带。

事实上他确实选择了腰带,这就是为什么蝙蝠侠穿着紧绷的橡胶衣,而没有穿裤子。

虽然nginx没有这样一条万能腰带,但是nginx有一个模块链(module chain),当nginx需要对应答进行gzip或chunked编码时,它会拿出一个模块来做这个工作。

当nginx基于IP或http认证来阻拦对某些资源的访问时,也是由一个模块来做这些工作的。

同样,当nginx需要和memcahed或者fastCGI交互时,也分别由对应的模块来做相应的工作。

尽管蝙蝠侠的万能腰带上有很多小玩意,但是有时候他还是需要一个新的小工具。

也许他有新的敌人,而他现在的武器(如batarang或bat-cuff)都不足以对付这个敌人。

也许他需要有新的技能,比如在水下呼吸。

所以他会让Lucius Fox来帮他设计这些小工具。

这个文档会告诉你nginx模块链表(module chain)的一些细节,这样你就可以做到像Lucius Fox一样。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

手把手教你开发Nginx模块前面的哪些话关于Nginx模块开发的博客资料,网上很多,很多。

但是,每篇博客都只提要点,无法"step by step"照着做,对于初次接触Nginx开发的同学,只能像只盲目的蚂蚁瞎燥急!该篇文章没有太多技术深度,只是一步一步说明白Nginx模块的开发过程。

开发环境搭建工欲善其事,必先利其器。

个人推荐Eclipse CDT 作为IDE,原因很简单,代码提示与补全功能很全,完胜Codeblock这类...相信与否,试过就知道。

在ubuntu下搭建开发环境:安装GCC编译器apt-get install build-essential安装pcre/openssl/zlib开发库apt-get install libpcre3-devapt-get install libssl-devapt-get install libzip-dev必需安装nginx核心模块依赖的pcre,openssl,zilib开发库安装JRE/Eclipse CDTapt-get install openjdk-8-jrewget http://ftp.yz.yamagata-u.ac.jp/pub/eclipse//technology/epp/downloads/release/neon/R/eclipse-cpp-neon-R-linux-gtk-x86_64.tar.gz && tzr -xzvf eclipse-cpp-neon-R-linux-gtk-x86_64.tar.gz下载nginx源码wget /download/nginx-1.10.1.tar.gz && tar -xzvf nginx-1.10.1.tar.gz配置CDT Build Environment添加变量,值Nginx src下各模块路径,用冒号分隔,例如:/root/Workspace/nginx-1.10.1/src/core:/root/Workspace/nginx-1.10.1/src/event:/root/Workspace/nginx-1.10.1/src/http:/root/Workspace/nginx-1.10.1/src/mail:/root/Workspace/n ginx-1.10.1/src/stream:/root/Workspace/nginx-1.10.1/src/os/unix添加环境变量,创建C项目时自动作为-I选项imageimageNginx模块编译流程Nginx使用configure脚本分析环境,自动生成objs结果。

哪么configure如何编译第三方模块?答案是--add-module指定第三方模块目录,并将目录存为$ngx_addon_dir环境变量。

执行$ngx_addon_dir/config脚本,读取模块配置。

在config中的环境变量分为2种:小写的本地环境变量,大写的全局环境变量。

例如:ngx_addon_name=ngx_http_mytest_moduleHTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module"NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_moudle.c"CORE_LIBS="$CORE_LIBS -lpcre"HTTP_MODULES中的ngx_http_mytest_module就是NGX_ADDON_SRCS中源码(如果有多个,都要写上)ngx_http_mytest_module.c中定义的ngx_module_t类型的全局变量。

可见,第三方模块的入口点就是ngx_module_t类型全局变量,该变量又关联ngx_http_module_t类型static变量,与ngx_command_t类型static数组。

在ngx_http_module_t中定义上下文配置nginx.conf解析的回调方法。

在ngx_command_t中定义配置项处理的set回调方法。

Nginx的全部操作都是异步的。

在上述的方法中根据需要又会使用其他handler方法。

以上可以看成Nginx第三方模块的起式。

Upstream例子源码configngx_addon_name=ngx_http_mytest_moduleHTTP_MODULES="$HTTP_MODULES ngx_http_mytest_module"NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest_module.c"源代码#include <ngx_config.h>#include <ngx_core.h>#include <ngx_http.h>#include <ngx_stream.h>typedef struct {ngx_http_upstream_conf_t upstream;} mytest_conf_t;typedef struct {ngx_http_status_t status;ngx_str_t backendServer;} mytest_ctx_t;static void *mytest_create_loc_conf(ngx_conf_t *cf);static char *mytest_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);static ngx_int_t mytest_upstream_create_request(ngx_http_request_t *r);static ngx_int_t mytest_upstream_process_status_line(ngx_http_request_t *r);static ngx_int_t mytest_upstream_process_header(ngx_http_request_t *r);static void mytest_upstream_finalize_request(ngx_http_request_t *r,ngx_int_t rc);static ngx_int_t mytest_handler(ngx_http_request_t *r);static char *mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static ngx_http_module_t mytest_ctx = {NULL,NULL,NULL,NULL,NULL,NULL,mytest_create_loc_conf,mytest_merge_loc_conf};static ngx_command_t mytest_commands[] = {{ngx_string("mytest"),NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LMT_CONF | NGX_CONF_NOARGS, mytest,NGX_HTTP_LOC_CONF_OFFSET,0,NULL},ngx_null_command};ngx_module_t ngx_http_mytest_module = {NGX_MODULE_V1,&mytest_ctx,mytest_commands,NGX_HTTP_MODULE,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NGX_MODULE_V1_PADDING};static ngx_str_t mytest_upstream_hide_headers[] ={ngx_string("Date"),ngx_string("Server"),ngx_string("X-Pad"),ngx_string("X-Accel-Expires"),ngx_string("X-Accel-Redirect"),ngx_string("X-Accel-Limit-Rate"),ngx_string("X-Accel-Buffering"),ngx_string("X-Accel-Charset"),ngx_null_string};static void *mytest_create_loc_conf(ngx_conf_t *cf){mytest_conf_t *mycf;mycf = (mytest_conf_t *)ngx_pcalloc(cf->pool, sizeof(mytest_conf_t));if(mycf == NULL){return NULL;}mycf->upstream.connect_timeout = 60000;mycf->upstream.send_timeout = 60000;mycf->upstream.read_timeout = 60000;mycf->upstream.store_access = 0600;mycf->upstream.buffering = 0;mycf->upstream.bufs.num = 8;mycf->upstream.bufs.size = ngx_pagesize;mycf->upstream.buffer_size = ngx_pagesize;mycf->upstream.busy_buffers_size = 2 * ngx_pagesize;mycf->upstream.temp_file_write_size = 2 * ngx_pagesize;mycf->upstream.max_temp_file_size = 1024 * 1024 *1024;mycf->upstream.hide_headers = NGX_CONF_UNSET_PTR;mycf->upstream.pass_headers = NGX_CONF_UNSET_PTR;return mycf;}static char *mytest_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child){mytest_conf_t *prev = (mytest_conf_t *)parent;mytest_conf_t *conf = (mytest_conf_t *)child;ngx_hash_init_t hash;hash.max_size = 100;hash.bucket_size = 1024; = "proxy_headers_hash";if(ngx_http_upstream_hide_headers_hash(cf,&conf->upstream, &prev->upstream,mytest_upstream_hide_headers,&hash)!=NGX_OK){ return NGX_CONF_ERROR;}return NGX_CONF_OK;}static ngx_int_t mytest_upstream_create_request(ngx_http_request_t *r){static ngx_str_t backendQueryLine = ngx_string("GET /search?q=%V HTTP/1.1\r\nHost: \r\nConnection: close\r\n\r\n");ngx_int_t queryLineLen = backendQueryLine.len + r->args.len - 2;ngx_buf_t *b = ngx_create_temp_buf(r->pool, queryLineLen);if(b == NULL) return NGX_ERROR;b->last = b->pos + queryLineLen;ngx_snprintf(b->pos, queryLineLen, (char *)backendQueryLine.data, &r->args);r->upstream->request_bufs = ngx_alloc_chain_link(r->pool);if(r->upstream->request_bufs == NULL) return NGX_ERROR;r->upstream->request_bufs->buf = b;r->upstream->request_bufs->next = NULL;r->upstream->request_sent = 0;r->upstream->header_sent = 0;r->header_hash = 1;return NGX_OK;}static ngx_int_t mytest_upstream_process_status_line(ngx_http_request_t *r){size_t len;ngx_int_t rc;ngx_http_upstream_t *u;mytest_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module);if(ctx == NULL) return NGX_ERROR;u = r->upstream;rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status);if(rc == NGX_AGAIN) return rc;if(rc == NGX_ERROR){ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent to valid HTTP/1.0 header");r->http_version = NGX_HTTP_VERSION_9;u->state->status = NGX_HTTP_OK;return NGX_OK;}if(u->state){u->state->status = ctx->status.code;}u->headers_in.status_n = ctx->status.code;len = ctx->status.end - ctx->status.start;u->headers_in.status_line.len = len;u->headers_in.status_line.data = ngx_pcalloc(r->pool, len);if(u->headers_in.status_line.data == NULL) return NGX_ERROR;ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len);u->process_header = mytest_upstream_process_header;return mytest_upstream_process_header(r);}static ngx_int_t mytest_upstream_process_header(ngx_http_request_t *r){ngx_int_t rc;ngx_table_elt_t *h;ngx_http_upstream_header_t *hh;ngx_http_upstream_main_conf_t *umcf;umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);for(;;){rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);if(rc == NGX_OK){h = ngx_list_push(&r->upstream->headers_in.headers);if(h == NULL) return NGX_ERROR;h->hash = r->header_hash;h->key.len = r->header_name_end - r->header_name_start;h->value.len = r->header_end - r->header_start;h->key.data = ngx_pcalloc(r->pool, h->key.len + 1 + h->value.len + 1 + h->key.len);if(h->key.data == NULL) return NGX_ERROR;h->value.data = h->key.data + h->key.len + 1;h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;ngx_memcpy(h->key.data, r->header_name_start, h->key.len);h->key.data[h->key.len]='\0';ngx_memcpy(h->value.data, r->header_start, h->value.len);h->value.data[h->value.len] = '\0';if(h->key.len == r->lowcase_index){ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);}else{ngx_strlow(h->lowcase_key, h->key.data, h->key.len);}hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len);if(hh && hh->handler(r, h, hh->offset)!=NGX_OK) return NGX_ERROR;continue;}if(rc == NGX_HTTP_PARSE_HEADER_DONE){if(r->upstream->headers_in.server == NULL){h = ngx_list_push(&r->upstream->headers_in.headers);if(h == NULL) return NGX_ERROR;h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');ngx_str_set(&h->key, "Server");ngx_str_null(&h->value);h->lowcase_key = (u_char *)"server";}if(r->upstream->headers_in.date == NULL){h = ngx_list_push(&r->upstream->headers_in.headers);if(h == NULL) return NGX_ERROR;h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');ngx_str_set(&h->key, "Date");ngx_str_null(&h->value);h->lowcase_key = (u_char *)"date";}return NGX_OK;}if(rc == NGX_AGAIN) return NGX_AGAIN;ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent invalid header");return NGX_HTTP_UPSTREAM_FT_INVALID_HEADER;}}static void mytest_upstream_finalize_request(ngx_http_request_t *r, ngx_int_t rc){ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "mytest_upstream_finalize_request");}static char *mytest(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 = mytest_handler;return NGX_CONF_OK;}static ngx_int_t mytest_handler(ngx_http_request_t *r){mytest_ctx_t *myctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module);if(myctx == NULL){myctx = ngx_pcalloc(r->pool, sizeof(mytest_ctx_t));if(myctx == NULL) return NGX_ERROR;ngx_http_set_ctx(r, myctx, ngx_http_mytest_module);}if(ngx_http_upstream_create(r)!=NGX_OK){ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_upstream_create() failed");return NGX_ERROR;}mytest_conf_t *mycf = (mytest_conf_t *)ngx_http_get_module_loc_conf(r, ngx_http_mytest_module);ngx_http_upstream_t *u = r->upstream;u->conf = &mycf->upstream;u->buffering = mycf->upstream.buffering;u->resolved = (ngx_http_upstream_resolved_t *) ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));if(u->resolved == NULL){ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_pcalloc resolved error. %s", strerror(errno));return NGX_ERROR;}static struct sockaddr_in backendSockAddr;struct hostent *pHost = gethostbyname((char *)"");if(pHost == NULL){ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gethostbyname fail. %s", strerror(errno));return NGX_ERROR;}backendSockAddr.sin_family = AF_INET;backendSockAddr.sin_port = htons((in_port_t)80);char *pDmsIP = inet_ntoa(*(struct in_addr *)(pHost->h_addr_list[0]));backendSockAddr.sin_addr.s_addr = inet_addr(pDmsIP);myctx->backendServer.data = (u_char *)pDmsIP;myctx->backendServer.len = strlen(pDmsIP);u->resolved->sockaddr = (struct sockaddr *)&backendSockAddr;u->resolved->port = htons((in_port_t)80);u->resolved->socklen = sizeof(struct sockaddr_in);u->resolved->naddrs = 1;u->create_request = mytest_upstream_create_request;u->process_header = mytest_upstream_process_status_line;u->finalize_request = mytest_upstream_finalize_request;r->main->count++;ngx_http_upstream_init(r);return NGX_DONE;}注意:《Nginx深入解析》的demo少了这句:“u->resolved->port = htons((in_port_t)80);”,否则报错“2016/09/09 11:24:18 [error] 28352#0: *1 no port in upstream "", client: 127.0.0.1, server: localhost, request: "GET /mytest?q=test HTTP/1.1", host: "localhost"”编译脚本./configure --prefix=/usr/local/nginx --add-module=/root/Workspace/nginx-modules/ngx_http_mytest_module --with-debugsudo makesudo make install安装后即可到/usr/local/nginx下配置nginx.conf进行测试。

相关文档
最新文档