博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Nginx源码分析(5)
阅读量:6082 次
发布时间:2019-06-20

本文共 4226 字,大约阅读时间需要 14 分钟。

  hot3.png

当需要为服务器增加一个自定义的扩展功能时,需要用到模块,相当于Nginx给开发者提供的一个模板范式。

比如现在实现一个网站的signin功能,用Flask框架可以这样实现:

@app.route('/signin', methods=['GET', 'POST'])def web_signin():	if request.method == 'GET':		return redirect(url_for('web'))	if request.method == 'POST':		name = request.form.get('username', None)		session['username'] = name		password = request.form.get('password', None)		db = LinkDB()		if name.strip()=='' or password.strip()=='':			return redirect(url_for('web'))		if db.has_user(name, password):			return render_template('page.html') 		else:			return '用户名或密码错误'

它实现的功能就是解析用户GETPOST过来的数据,然后构造相应的响应。这和Nginx的handler模块所做的工作相似。

Nginx本身做的工作实际很少,当它接到一个HTTP请求时,它仅仅是通过查找配置文件将此次请求映射到一个location block,而此location中所配置的各个指令则会启动不同的模块去完成工作,因此模块可以看做Nginx真正的劳动工作者。下图表示一次请求和相应的完整过程。

输入图片说明

现在在浏览器中输入http://127.0.0.1/hello_world,让浏览器显示 hello_world, testing!!!怎么实现呢?这需要我们编写一个hello handler模块。

模块定义ngx_module_t

开发一个模块,需要定义一个ngx_module_t类型的变量来说明这个模块的信息。它定义在/nginx/src/core/ngx_config_file中。

struct ngx_module_s {    ngx_uint_t            ctx_index;    ngx_uint_t            index;    ngx_uint_t            spare0;    ngx_uint_t            spare1;    ngx_uint_t            spare2;    ngx_uint_t            spare3;    ngx_uint_t            version;    void                 *ctx;    ngx_command_t        *commands;    ngx_uint_t            type;    ngx_int_t           (*init_master)(ngx_log_t *log);    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);    void                (*exit_thread)(ngx_cycle_t *cycle);    void                (*exit_process)(ngx_cycle_t *cycle);    void                (*exit_master)(ngx_cycle_t *cycle);    //...};

hello模块定义如下:

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,    NULL,    NULL,    NULL,    NULL,    NULL,    NULL,    NULL,    NGX_MODULE_V1_PADDING};

模块的编写步骤是:

  • 这里是列表文本 编写模块基本结构。包括模块的定义,模块上下文结构,模块的配置结构等。
  • 实现handler的挂载函数。根据模块的需求选择正确的挂载方式。
  • 编写handler处理函数。模块的功能主要通过这个函数来完成。这是最关键的,hello模块的功能是简单返回一个字符串。在ngx_http_hello_world_handler中实现。
static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t* r) {    ngx_int_t rc;    ngx_buf_t* b;    ngx_chain_t out[2];    ngx_http_hello_world_loc_conf_t* hlcf;    hlcf = ngx_http_get_module_loc_conf(r, ngx_http_hello_world_module);    // 设置 request 的 header    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));    // 第 1 块缓冲区    out[0].buf = b;    out[0].next = &out[1];    // 本模块中,缓冲区只需要写入数据,所以只设置 pos 和 last    b->pos = (u_char*)"hello_world, ";    b->last = b->pos + sizeof("hello_world, ") - 1;    b->memory = 1; // 标示缓冲区是内存缓冲    // 分配缓冲区的内存空间    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));    // 第 2 块缓冲区    out[1].buf = b;    out[1].next = NULL;    // 本模块中,缓冲区只需要写入数据,所以只设置 pos 和 last    b->pos = hlcf->output_words.data;    b->last = hlcf->output_words.data + (hlcf->output_words.len);    b->memory = 1; // 标示缓冲区是内存缓冲    b->last_buf = 1; // 标示整个响应最后一个缓冲区,nginx会立即发送缓冲的所有数据    // 设置 request 的 header    r->headers_out.status = NGX_HTTP_OK;    r->headers_out.content_length_n = hlcf->output_words.len + sizeof("hello_world, ") - 1;    // 发送 request    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[0]);}

配置和编译

在Nginx文件夹下

mkdir ngx_http_hello_world_modulecd ngx_http_hello_world_moduletouch ngx_http_hello_world_module.ctouch config

ngx_http_hello_world_module.c是主要的函数,config是配置文件。

在配置文件中加入

ngx_addon_name=ngx_http_hello_moduleHTTP_MODULES="$HTTP_MODULES ngx_http_hello_world_module"NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_hello_world_module.c"

这个config文件的内容就是告诉nginx的编译脚本,该如何进行编译。

./configure  --add-module=/home/hy/Desktop/nginx/ngx_http_hello_world_modulemakemake install

add-module后接上文中新建目录的路径。

##使用

/usr/local/nginx/conf路径下的nginx.conf文件中加入

location /hello_world {    hello_world testing!!!;}

访问http://127.0.0.1/hello_world即可看见成功的页面。

输入图片说明

##参考

转载于:https://my.oschina.net/lvyi/blog/423842

你可能感兴趣的文章
Linux系统磁盘管理
查看>>
hdu 2191 (多重背包+二进制优化)
查看>>
home.php
查看>>
neo4j---删除关系和节点
查看>>
redis分布式锁redisson
查看>>
什么样的企业可以称之为初创企业?
查看>>
Python爬虫之BeautifulSoup
查看>>
《HTML 5与CSS 3权威指南(第3版·下册)》——第20章 使用选择器在页面中插入内容...
查看>>
如何判断自己适不适合做程序员?这几个特点了解一下
查看>>
newinstance()和new有什么区别
查看>>
android下载封装类
查看>>
[node] 用 node-webkit 开发桌面应用
查看>>
Nginx访问控制和虚拟主机
查看>>
report widget not working for external users
查看>>
windows phone 摄像头得到图片是旋转90°
查看>>
Linux--sed使用
查看>>
没有显示器的情况下安装和使用树莓派
查看>>
【android】使用handler更新UI
查看>>
mochiweb 源码阅读(十五)
查看>>
前端面试中的常见的算法问题
查看>>