Nginx学习(7)—http过滤模块(2)

来源:互联网 发布:上海软件研发质量咨询 编辑:程序博客网 时间:2024/05/16 07:57

实例

场景:用户请求由static静态文件模块进行处理,根据URI返回磁盘文件给用户。我们开发的过滤模块会在返回给用户的响应包体前加一段字符串:“[my filter prefix]”

关于实例的执行流程,具体包括头部处理与包体处理,具体如下:

整个ngx_http_mytest_filter_module.c文件如下:
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * Copyright (C) Igor Sysoev 
  3.  * Copyright (C) Nginx, Inc. 
  4.  */  
  5.   
  6. #include <ngx_config.h>  
  7. #include <ngx_core.h>  
  8. #include <ngx_http.h>  
  9.   
  10. typedef struct {  
  11.     ngx_flag_t enable;  
  12. } ngx_http_mytest_filter_conf_t;  
  13.   
  14. typedef struct {  
  15.     ngx_int_t add_prefix;  
  16. } ngx_http_mytest_filter_ctx_t;  
  17.   
  18. static ngx_int_t  
  19. ngx_http_mytest_fliter_init(ngx_conf_t *cf);  
  20. static void *  
  21. ngx_http_mytest_filter_create_conf(ngx_conf_t *cf);  
  22. static void *  
  23. ngx_http_mytest_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child);  
  24.   
  25.   
  26.   
  27. static ngx_command_t ngx_http_mytest_filter_commands[] = {  
  28.   
  29.     { ngx_string("add_prefix"),  
  30.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|  
  31.       NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS,  
  32.       ngx_conf_set_flag_slot,  
  33.       NGX_HTTP_LOC_CONF_OFFSET,  
  34.       offsetof(ngx_http_mytest_filter_conf_t, enable),  
  35.       NULL},  
  36.   
  37.       ngx_null_command  
  38. };  
  39.   
  40. static ngx_http_module_t  ngx_http_mytest_filter_module_ctx = {  
  41.     NULL,                                  /* preconfiguration */  
  42.     ngx_http_mytest_fliter_init,           /* postconfiguration */  
  43.   
  44.     NULL,                                  /* create main configuration */  
  45.     NULL,                                  /* init main configuration */  
  46.   
  47.     NULL,                                  /* create server configuration */  
  48.     NULL,                                  /* merge server configuration */  
  49.   
  50.     ngx_http_mytest_filter_create_conf,    /* create location configuration */  
  51.     ngx_http_mytest_filter_merge_conf      /* merge location configuration */  
  52. };  
  53.   
  54. ngx_module_t  ngx_http_mytest_module = {  
  55.     NGX_MODULE_V1,  
  56.     &ngx_http_mytest_filter_module_ctx,    /* module context */  
  57.     ngx_http_mytest_filter_commands,       /* module directives */  
  58.     NGX_HTTP_MODULE,                       /* module type */  
  59.     NULL,                                  /* init master */  
  60.     NULL,                                  /* init module */  
  61.     NULL,                                  /* init process */  
  62.     NULL,                                  /* init thread */  
  63.     NULL,                                  /* exit thread */  
  64.     NULL,                                  /* exit process */  
  65.     NULL,                                  /* exit master */  
  66.     NGX_MODULE_V1_PADDING  
  67. };  
  68.   
  69. static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;  
  70. static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;  
  71.   
  72. static ngx_str_t filter_prefix = ngx_string("[my filter prefix]");  
  73.   
  74. static ngx_int_t  
  75. ngx_http_mytest_header_filter(ngx_http_request_t *r)  
  76. {  
  77.     ngx_http_mytest_filter_ctx_t      *ctx;  
  78.     ngx_http_mytest_filter_conf_t     *conf;  
  79.   
  80.     if (r->headers_out.status != NGX_HTTP_OK) {  
  81.         return ngx_http_next_header_filter(r);  
  82.     }  
  83.   
  84.     /* 获取HTTP上下文 */  
  85.     ctx = ngx_http_get_module_ctx(r, ngx_http_mytest_filter_module);  
  86.     if (ctx) {  
  87.         /* 如果已存在,说明已被调用 */  
  88.         return ngx_http_next_header_filter(r);   
  89.     }  
  90.   
  91.     conf = ngx_http_get_module_loc_conf(r, ngx_http_mytest_filter_module);  
  92.   
  93.     if (conf->enable == 0) {  
  94.         return ngx_http_next_header_filter(r);  
  95.     }  
  96.   
  97.     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_mytest_filter_ctx_t));  
  98.     if (ctx == NULL) {  
  99.         return NGX_ERROR;  
  100.     }  
  101.   
  102.     ctx->add_prefix = 0;  
  103.   
  104.     ngx_http_set_ctx(r, ctx, ngx_http_mytest_filter_module);  
  105.   
  106.     if (r->headers_out.content_type.len >= sizeof("text/plain") - 1  
  107.             && ngx_strncasecmp(r->headers_out.content_type.data,  
  108.                 (u_char *)"text/plain"sizeof("text/plain") - 1) == 0) {  
  109.         ctx->add_prefix = 1;  
  110.   
  111.         if (r->headers_out.content_length_n > 0) {  
  112.             r->headers_out.content_length_n += filter_prefix.len;  
  113.         }  
  114.   
  115.         return ngx_http_next_header_filter(r);  
  116.     }  
  117. }  
  118.   
  119. static ngx_int_t  
  120. ngx_http_mytest_body_filter(ngx_http_request_t *r)  
  121. {  
  122.     ngx_http_mytest_filter_ctx_t      *ctx;  
  123.   
  124.     ctx = ngx_http_get_module_ctx(r, ngx_http_mytest_filter_module);  
  125.     if (ctx == NULL || ctx->add_prefix != 1) {  
  126.         return ngx_http_next_body_filter(r);  
  127.     }  
  128.   
  129.     ctx->add_prefix = 2;  
  130.   
  131.     ngx_buf_t *b = ngx_create_temp_buf(r->pool, filter_prefix.len);  
  132.   
  133.     b->start = b->pos = filter_prefix.data;  
  134.     b->last = b->pos + filter_prefix.len;  
  135.   
  136.     ngx_chain_t *cl = ngx_alloc_chain_link(r->pool);  
  137.     cl->buf = b;  
  138.     cl->next = NULL;  
  139.   
  140.     return ngx_http_next_body_filter(r, cl);  
  141. }  
  142.   
  143. static ngx_int_t  
  144. ngx_http_mytest_fliter_init(ngx_conf_t *cf)  
  145. {  
  146.     ngx_http_next_header_filter = ngx_http_top_header_filter;  
  147.     ngx_http_top_header_filter = ngx_http_mytest_header_filter;  
  148.   
  149.     ngx_http_next_header_filter = ngx_http_top_body_filter;  
  150.     ngx_http_top_header_filter = ngx_http_mytest_body_filter;  
  151.   
  152.     return NGX_OK;  
  153. }  
  154.   
  155. static void *  
  156. ngx_http_mytest_filter_create_conf(ngx_conf_t *cf)  
  157. {  
  158.     ngx_http_mytest_filter_conf_t *mycf;  
  159.   
  160.     /* 创建配置结构体 */  
  161.     mycf = (ngx_http_mytest_filter_conf_t *)ngx_pcalloc(cf->pool,   
  162.                 sizeof(ngx_http_mytest_filter_conf_t));  
  163.     if (mycf == NULL) {  
  164.         return NULL;  
  165.     }  
  166.       
  167.     mycf->enable = NGX_CONF_UNSET;     
  168.       
  169.     return mycf;  
  170. }  
  171.   
  172. static void *  
  173. ngx_http_mytest_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)  
  174. {  
  175.     ngx_http_mytest_filter_conf_t *prev = (ngx_http_mytest_filter_conf_t *)parent;  
  176.     ngx_http_mytest_filter_conf_t *conf = (ngx_http_mytest_filter_conf_t *)child;  
  177.   
  178.     ngx_conf_merge_value(conf->enable, prev->enable, 0);  
  179.   
  180.     return NGX_OK;  
  181. }  

总结

基本上是对HTTP模块开发流程的复习,另外怎么查看执行这个程序执行后的结果啊。好吧,这个我再查查。。下章开始Nginx高级数据结构的学习。再之后就开始第三部分的源码深入了。这才是重点,前面都只是铺垫。。。
0 0
原创粉丝点击