zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Python使用SMTP模块、email模块发送邮件
    harbor搭建及使用
    ELK搭建-windows
    ELK技术栈之-Logstash详解
    【leetcode】1078. Occurrences After Bigram
    【leetcode】1073. Adding Two Negabinary Numbers
    【leetcode】1071. Greatest Common Divisor of Strings
    【leetcode】449. Serialize and Deserialize BST
    【leetcode】1039. Minimum Score Triangulation of Polygon
    【leetcode】486. Predict the Winner
  • 原文地址:https://www.cnblogs.com/ourroad/p/4863051.html
Copyright © 2011-2022 走看看