nginx模块开发之“敲录”

简介: 声明:      敲录:自己动手照敲录入。      nginx支持高并发,占用少量系统资源的webserver。如果听说某人会nginx模块开发,我们暗赞-------高大上。其实不然,只要你树立目标,暗下苦工,明天的你就是“高富帅”。
声明:
      敲录:自己动手照敲录入。


      nginx支持高并发,占用少量系统资源的webserver。如果听说某人会nginx模块开发,我们暗赞-------高大上。其实不然,只要你树立目标,暗下苦工,明天的你就是“高富帅”。我在2012年下半年就树立目标,研读nginx代码,工具就是GOOG,中间断断续续。到13年下半年,稍稍有点成绩,可以照葫芦画瓢,搞点小东西,原理层面的东西,并不是很理解。后来朋友推荐,看到了陶辉老师写的“深入理解Nginx”,发现很是值得我们细细品味。下面是我敲录的一个模块代码:
    
第一步:查看文件
[root@centos6 nginx-http-top-filter-1.1.1]# ll
total 12
-rw-r--r-- 1 root root  189 Feb 25 17:29 config
-rw-r--r-- 1 root root 5094 Mar 15 20:13 ngx_http_top_filter_module.c

第二步:编辑config配置文件
[root@centos6 nginx-http-top-filter-1.1.1]# vim config   #编辑config配置文件

ngx_addon_name=ngx_http_top_filter_module
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES ngx_http_top_filter_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ ngx_http_top_filter_module.c"

第三步:编写模块
[root@centos6 nginx-http-top-filter-1.1.1]# vim ngx_http_top_filter_module.c
#include
#include
#include


typedef struct {
    ngx_flag_t enable;
} ngx_http_top_conf_t;

typedef struct {
    ngx_int_t add_prefix;

} ngx_http_top_ctx_t;

static void *ngx_http_top_create_conf(ngx_conf_t *cf);
static char *ngx_http_top_merge_conf(ngx_conf_t *cf, void *parent, void *child);
static ngx_int_t ngx_http_top_filter_init(ngx_conf_t *cf);
static ngx_int_t ngx_http_topfilter_header_filter(ngx_http_request_t *r);
static ngx_int_t ngx_http_topfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in);

static ngx_str_t filter_prefix = ngx_string("[my filter prefix]");

/*----step------3--------*/
static ngx_command_t  ngx_http_top_filter_commands[] = {
{ ngx_string("add_prefix"),
      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_top_conf_t,enable),
      NULL },

      ngx_null_command
};

/*----step------2--------*/
static ngx_http_module_t  ngx_http_top_filter_module_ctx = {
    NULL,                               /* proconfiguration */
    ngx_http_top_filter_init,        /* postconfiguration */

    NULL,                               /* create main configuration */
    NULL,                               /* init main configuration */

    NULL,                               /* create server configuration */
    NULL,                               /* merge server configuration */

    ngx_http_top_create_conf,    /* create location configuration */
    ngx_http_top_merge_conf      /* merge location configuration */
};
/*-----step-------1--------------------------*/
ngx_module_t  ngx_http_top_filter_module = {
    NGX_MODULE_V1,
    &ngx_http_top_filter_module_ctx, /* module context */
    ngx_http_top_filter_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_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt   ngx_http_next_body_filter;

/*----step----4----------------*/
static ngx_int_t
ngx_http_topfilter_header_filter(ngx_http_request_t *r)
{
    ngx_http_top_ctx_t *ctx;
    ngx_http_top_conf_t *conf;

    if(r->headers_out.status != NGX_HTTP_OK){
return ngx_http_next_header_filter(r);
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_top_filter_module);

    if(ctx){
        return ngx_http_next_header_filter(r);
    }

    conf = ngx_http_get_module_loc_conf(r, ngx_http_top_filter_module);

    if(conf->enable ==0){
        return ngx_http_next_header_filter(r);
    }

    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_top_ctx_t));
    if(ctx == NULL){
        return NGX_ERROR;
    }

    ctx->add_prefix = 0;
    ngx_http_set_ctx(r, ctx, ngx_http_top_filter_module);
    /*注意测试文件后缀必须是.txt,如果是html,需要将红色部分修改,原因自己想想,会明白的,当时我测试的时候,也想了一下。 */
    if(r->headers_out.content_type.len >= sizeof(" text/plain") -1 && ngx_strncasecmp(r->headers_out.content_type.data, (u_
char *) "text/plain", sizeof("text/plain") -1) ==0){
        ctx->add_prefix = 1;

        if(r->headers_out.content_length_n > 0)
        {
            r->headers_out.content_length_n += filter_prefix.len;
        }

    }
    return ngx_http_next_header_filter(r);

}

static void *ngx_http_top_create_conf(ngx_conf_t *cf)
{
    ngx_http_top_conf_t  *mycf;

    mycf = (ngx_http_top_conf_t *)ngx_pcalloc(cf->pool, sizeof(ngx_http_top_conf_t));
    if (mycf == NULL) {
        return NULL;
    }

    mycf->enable= NGX_CONF_UNSET;

    return mycf;
}

static char *
ngx_http_top_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_top_conf_t  *prev = (ngx_http_top_conf_t *)parent;
    ngx_http_top_conf_t  *conf = (ngx_http_top_conf_t *)child;

    ngx_conf_merge_value(conf->enable, prev->enable, 0);

    return NGX_CONF_OK;
}


    static ngx_int_t
ngx_http_top_filter_init(ngx_conf_t *cf)
{

    ngx_http_next_header_filter = ngx_http_top_header_filter;
    ngx_http_top_header_filter = ngx_http_topfilter_header_filter;

    ngx_http_next_body_filter = ngx_http_top_body_filter;
    ngx_http_top_body_filter = ngx_http_topfilter_body_filter;


    return NGX_OK;
}

static ngx_int_t ngx_http_topfilter_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
ngx_http_top_ctx_t *ctx;
    ctx = ngx_http_get_module_ctx(r, ngx_http_top_filter_module);

    if(ctx == NULL){
        return ngx_http_next_body_filter(r, in);
    }

    ctx->add_prefix = 2;
    ngx_buf_t *b = ngx_create_temp_buf(r->pool, filter_prefix.len);


    b->pos = filter_prefix.data;
    b->last = b->pos + filter_prefix.len;
    b->start = b->pos;

    ngx_chain_t *c1 = ngx_alloc_chain_link(r->pool);
    if (c1 == NULL )
    {
        return NGX_ERROR;
    }

    c1->buf = b;
    c1->next = in;

    return ngx_http_next_body_filter(r, c1);

}

       文档中的数字标号,是我自己搞的标注,方便阅读用的。线上环l境中用的一个nginx修改版,最近在想怎样通过模块的方式实现,但是还没搞好,改天搞好以后,再贴到这里。
目录
相关文章
|
6月前
|
应用服务中间件 nginx
Nginx安装nginx-rtmp-module模块
【2月更文挑战第4天】 nginx中的模块虽然就是类似插件的概念,但是它无法像VsCode那样轻松的安装扩展。 nginx要安装其它模块必须同时拿到nginx源代码和模块源代码,然后手动编译,将模块打到nginx中,最终生成一个名为nginx的可执行文件。
511 6
|
6月前
|
应用服务中间件 nginx
百度搜索:蓝易云【利用nginx内置ngx_http_mirror_module模块实现流量复制及流量放大】
以上就是使用Nginx内置 `ngx_http_mirror_module`模块实现流量复制和流量放大的简要示例。通过合理配置和利用该模块,可以实现更复杂的流量控制和调试需求。
109 1
|
3月前
|
负载均衡 应用服务中间件 API
Nginx:location配置模块的用法(一)
Nginx:location配置模块的用法(一)
426 2
|
1月前
|
应用服务中间件 nginx C++
nginx的cgi模块
nginx的cgi模块
24 0
|
3月前
|
缓存 应用服务中间件 nginx
安装nginx-http-flv-module模块
本文介绍如何为Nginx安装`nginx-http-flv-module`模块。此模块基于`nginx-rtmp-module`二次开发,不仅具备原模块的所有功能,还支持HTTP-FLV播放、GOP缓存、虚拟主机等功能。安装步骤包括:确认Nginx版本、下载相应版本的Nginx与模块源码、重新编译Nginx并加入新模块、验证模块安装成功。特别注意,此模块已包含`nginx-rtmp-module`功能,无需重复编译安装。
160 1
|
3月前
|
负载均衡 应用服务中间件 Linux
在Linux中,常用的 Nginx 模块有哪些,常来做什么?
在Linux中,常用的 Nginx 模块有哪些,常来做什么?
|
3月前
|
缓存 前端开发 应用服务中间件
Nginx:location配置模块的用法(二)
Nginx:location配置模块的用法(二)
93 2
|
4月前
|
应用服务中间件 Linux nginx
FFmpeg开发笔记(四十)Nginx集成rtmp模块实现RTMP推拉流
《FFmpeg开发实战》书中介绍了如何使用FFmpeg向网络推流,简单流媒体服务器MediaMTX不适用于复杂业务。nginx-rtmp是Nginx的RTMP模块,提供基本流媒体服务。要在Linux上集成rtmp,需从官方下载nginx和nginx-rtmp-module源码,解压后在nginx目录配置并添加rtmp模块,编译安装。配置nginx.conf启用RTMP服务,监听1935端口。使用ffmpeg推流测试,如能通过VLC播放,表明nginx-rtmp运行正常。更多详情见书本。
110 0
FFmpeg开发笔记(四十)Nginx集成rtmp模块实现RTMP推拉流
|
3月前
|
Ubuntu 前端开发 JavaScript
如何在 Ubuntu 14.04 上为 Nginx 添加 gzip 模块
如何在 Ubuntu 14.04 上为 Nginx 添加 gzip 模块
24 0
|
6月前
|
Ubuntu 应用服务中间件 nginx
ubuntu编译安装nginx及安装nginx_upstream_check_module模块
以上是编译安装Nginx和安装 `nginx_upstream_check_module`模块的基本步骤。根据你的需求和环境,你可能需要进一步配置Nginx以满足特定的要求。
264 3