• NGINX(六)扩展


    前言

    nginx模块化设计, 添加扩展模块变得容易, 下面开发一个非常简单的扩展模块, 实现返回http请求的头部内容, 配置标记是ping_pong, 配置在NGX_HTTP_LOC_CONF中.

    HTTP处理阶段

    nginx处理http请求分为很多的阶段, 下面列出了所有阶段, 服务器接收到完http请求头部内容后, 会依次执行各个阶段, 执行顺序按照全局ngx_modules数组中的顺序进行. ngxin如何知道我们的模块是http处理的一个阶段呢, 阶段模块在初始化时, 要将自己注册进模块列表中, 后面我们自己模块代码会有体现.

    typedef enum {
        NGX_HTTP_POST_READ_PHASE = 0,
    	
        NGX_HTTP_SERVER_REWRITE_PHASE,
    	
        NGX_HTTP_FIND_CONFIG_PHASE,
    	
        NGX_HTTP_REWRITE_PHASE,
        NGX_HTTP_POST_REWRITE_PHASE,
    
        NGX_HTTP_PREACCESS_PHASE,
    
        NGX_HTTP_ACCESS_PHASE,
        NGX_HTTP_POST_ACCESS_PHASE,
    
        NGX_HTTP_TRY_FILES_PHASE,
    	
    	/*http请求内容处理, 生成内容, 过滤操作, 我们要实现的简单扩展就注册在这个阶段*/
        NGX_HTTP_CONTENT_PHASE,
    
        NGX_HTTP_LOG_PHASE
    } ngx_http_phases;
    
    
    /*
     *http请求头部接收完之后, 会执行ngx_http_core_run_phases函数, 函数遍历所有阶段进行执行.
     */
    void
    ngx_http_core_run_phases(ngx_http_request_t *r)
    {
        ngx_int_t                   rc;
        ngx_http_phase_handler_t   *ph;
        ngx_http_core_main_conf_t  *cmcf;
    
        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
    
        ph = cmcf->phase_engine.handlers;
    
        while (ph[r->phase_handler].checker) {
    	
    		/*执行每个阶段的回调函数*/
            rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
    		
    		/*一旦有阶段返回NGX_OK标记, 则立即返回, 后面的阶段不再执行*/
            if (rc == NGX_OK) {
                return;
            }
        }
    }
    

    ps : 各个阶段具体处理什么参考博客 http://blog.csdn.net/fengmo_q/article/details/8594610

    编译选项

    --with-http_ping_pong_module
    

    编译配置:

    1.1.auto/options中添加

    --with-http_ping_pong_module)    HTTP_PING_PONG=YES         ;;
    

    2.2.auto/modules中添加

    if [ $HTTP_PING_PONG = YES ]; then
        HTTP_MODULES="$HTTP_MODULES $HTTP_PING_PONG_MODULE"
        HTTP_SRCS="$HTTP_SRCS src/http/modules/ngx_http_ping_pong_module.c"
    fi
    

    3.3.auto/sources中添加

    HTTP_PING_PONG_MODULE=ngx_http_ping_pong_module
    HTTP_PING_PONG_SRCS=src/http/modules/ngx_http_ping_pong_module.c
    

    nginx.conf中配置示例

        server {
            listen       88;
    
            location /test {
                ping_pong on;
            }
        }
    

    完整ngx_http_ping_pong_module.c

    /*
     * Copyright (C) Igor Sysoev
     * Copyright (C) Nginx, Inc.
     */
    
    
    #include <ngx_config.h>
    #include <ngx_core.h>
    #include <ngx_http.h>
    
    
    static ngx_int_t ngx_http_ping_pong_handler(ngx_http_request_t *r);
    static ngx_int_t ngx_http_ping_pong_init(ngx_conf_t *cf);
    static char* ngx_http_ping_pong_set_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    static void* ngx_http_ping_pong_create_loc_conf(ngx_conf_t *cf);
    
    typedef struct{
        ngx_int_t ping_pong;
    }ngx_http_ping_pong_loc_conf_t;
    
    static ngx_command_t ngx_http_ping_pong_commands[] = {
        
        { ngx_string("ping_pong"),
          NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
          ngx_http_ping_pong_set_conf,
          NGX_HTTP_LOC_CONF_OFFSET,
          offsetof(ngx_http_ping_pong_loc_conf_t, ping_pong),
          NULL },
    
        ngx_null_command
    };
    
    ngx_http_module_t  ngx_http_ping_pong_module_ctx = {
        NULL,                                  /* preconfiguration */
        ngx_http_ping_pong_init,               /* postconfiguration */
    
        NULL,                                  /* create main configuration */
        NULL,                                  /* init main configuration */
    
        NULL,                                  /* create server configuration */
        NULL,                                  /* merge server configuration */
    
        ngx_http_ping_pong_create_loc_conf,    /* create location configuration */
        NULL                                   /* merge location configuration */
    };
    
    
    ngx_module_t  ngx_http_ping_pong_module = {
        NGX_MODULE_V1,
        &ngx_http_ping_pong_module_ctx,        /* module context */
        ngx_http_ping_pong_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_ping_pong_handler(ngx_http_request_t *r)
    {
        ngx_int_t rc;
        ngx_buf_t* b;
        ngx_chain_t out;
        ngx_uint_t content_length = 0;
        u_char ngx_ping_pong_string[1024] = {0};
        ngx_http_ping_pong_loc_conf_t* lcf;
    	
    	/*获取并检查是否配置了ping_pong标记*/
        lcf = ngx_http_get_module_loc_conf(r, ngx_http_ping_pong_module);
        if (lcf->ping_pong == NGX_CONF_UNSET)
        {
    		/*如果没有进行配置, 则继续执行后面阶段*/
            return NGX_DECLINED;
        }
    	
    	/* 格式化输出的内容 */
        ngx_sprintf(ngx_ping_pong_string, "%V:%V,%V,%V  %V:%V", &r->method_name, &r->uri, &r->args, &r->request_line,  &r->headers_in.host->key, &r->headers_in.host->value);
        content_length = ngx_strlen(ngx_ping_pong_string);
    	
    	/*丢弃请求内容, 用不到*/
        rc = ngx_http_discard_request_body(r);
        if (rc != NGX_OK)
            return rc;
    
        ngx_str_set(&r->headers_out.content_type, "text/html");
    
        b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
        if (b == NULL)
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
    
        out.buf = b;
        out.next = NULL;
    	
    	/*构造一个输出buf*/
        b->pos = ngx_ping_pong_string;
        b->last = ngx_ping_pong_string + content_length;
        b->memory = 1;
        b->last_buf = 1;
    
        r->headers_out.status = NGX_HTTP_OK;
        r->headers_out.content_length_n = content_length;
    	
    	/*http响应头部返回给客户端*/
        rc = ngx_http_send_header(r);
    
        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
            return rc;
    	
    	/*http响应内容返回给客户端*/
        return ngx_http_output_filter(r, &out);
    }
    
    /*
     *由于我们配置非常简单, 因此这里其实不用单独写set函数的, 可以直接将ngx_conf_set_flag_slot配置到command配置中
     */
    static char*
    ngx_http_ping_pong_set_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {
        char* rv = ngx_conf_set_flag_slot(cf, cmd, conf);
        return rv;
    }
    
    /*
     *初始化配置
     */
    static void*
    ngx_http_ping_pong_create_loc_conf(ngx_conf_t *cf)
    {
        ngx_http_ping_pong_loc_conf_t* lcf = NULL;
        lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ping_pong_loc_conf_t));
        if (lcf == NULL)
        {
            return NULL;
        }
    
        lcf->ping_pong = NGX_CONF_UNSET;
    
        return lcf;
    }
    
    /*
     *模块初始化时, 将阶段处理的回调函数注册进相应的阶段
     */
    static ngx_int_t
    ngx_http_ping_pong_init(ngx_conf_t *cf)
    {
        ngx_http_handler_pt        *h;
        ngx_http_core_main_conf_t  *cmcf;
    
        cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
    	
    	/*每个阶段都有一个处理函数的数组, 将我们执行的函数放入数组中*/
        h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
        if (h == NULL) {
            return NGX_ERROR;
        }
    
        *h = ngx_http_ping_pong_handler;
    
        return NGX_OK;
    }
    
  • 相关阅读:
    IS上部署MVC网站,打开后ExtensionlessUrlHandler-
    深拷贝与浅拷贝
    python小技巧---打印出不同颜色的输出
    环境搭建之allure的安装配置,及简单使用
    Python进行JSON格式化输出,以及汉字显示问题
    无限遍历,Python实现在多维嵌套字典、列表、元组的JSON中获取数据
    环境准备—之—linux下安装svn--开机自启--及format权限问题
    环境准备—之—linux下安装python3和pip3
    环境准备—之—linux下安装jdk
    问题1——之Linux虚拟机ip地址消失
  • 原文地址:https://www.cnblogs.com/ourroad/p/4863051.html
Copyright © 2020-2023  润新知