`

Apache module杂记

阅读更多
可以基于正则表达式修改文本内容的Apache module:
mod_sed:实现了类似sed功能的module,可以通过正则表达式修改文本内容。apache2.3中加入了这个module,但是这个module也可以用于apache 2.0版本。可以到http://src.opensolaris.org/source/xref/webstack/mod_sed/下载源代码,README里有相应的编译命令:/http安装路径/bin/apxs -i -c mod_sed.c regexp.c sed0.c sed1.c

mod_substitute:功能和mod_sed类似,默认加入到apache2.2中http://httpd.apache.org/docs/2.2/mod/mod_substitute.html

mod_line_edit:也可以基于正则表达式替换文本内容,可以就该html/css/javascript。但是它和前两者不同的是mod_line_edit的to-pattern可以使用Apache的环境变量http://apache.webthing.com/mod_line_edit/,这个功能正是我最近需要的。
例如下面的配置可以在<head>标签后插入一个<meta/>标签并且可以将环境变量UNIQUE_ID的值添加到meta的属性中去(UNIQUE_ID环境变量需要mod_unique_id的支持http://lamp.linux.gov.cn/Apache/ApacheMenu/mod/mod_unique_id.html
LERewriteRule "<head>" "<head><meta http-equiv='REQUEST-ID' content='${UNIQUE_ID}' />" iV


mod_proxy_html:可以基于html标签进行比较比较精细的内容修改操作http://apache.webthing.com/mod_proxy_html/

以上这些module都是基于apache的过滤器的功能来完成对相应内容的修改(类似servlet里的filter)http://lamp.linux.gov.cn/Apache/ApacheMenu/filter.html


mod_line_edit使用经验:
1.mod_line_edit的性能问题:考虑到系统中有500-700K的html页面,因此我就对mod_line_edit在展现1M的静态html做了一下压力测试。测试结果非常不理想,在不添加mod_line_edit时TPS在500+,加上mod_line_edit后tps只有1(狂汗...)。
2.mod_line_edit的代码分析:
  /* mod_line_edit顾名思义就是对文本内容按行进行编辑,
   * 因此mod要先对输出流进行整理,每一行内容收集到一个apr_bucket里,
   * 然后将所有行数据放到bbline中,下面的代码实现的就是这个用途。
   */
  bbline = apr_brigade_create(f->r->pool, f->c->bucket_alloc) ;

  /* first ensure we have no mid-line breaks that might be in the
   * middle of a search string causing us to miss it!  At the same
   * time we split into lines to avoid pattern-matching over big
   * chunks of memory.
   */
  while ( b != APR_BRIGADE_SENTINEL(bb) ) {
    if ( !APR_BUCKET_IS_METADATA(b) ) {
      if ( apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS ) {
	if ( bytes == 0 ) {
	  APR_BUCKET_REMOVE(b) ;
	} else while ( bytes > 0 ) {
	  switch (cfg->lineend) {

	  case LINEEND_UNIX:
	    le = memchr(buf, '\n', bytes) ;
	    break ;

	  case LINEEND_MAC:
	    le = memchr(buf, '\r', bytes) ;
	    break ;

	  case LINEEND_DOS:
	    /* Edge-case issue: if a \r\n spans buckets it'll get missed.
	     * Not a problem for present purposes, but would be an issue
	     * if we claimed to support pattern matching on the lineends.
	     */
	    found = 0 ;
	    le = memchr(buf+1, '\n', bytes-1) ;
	    while ( le && !found ) {
	      if ( le[-1] == '\r' ) {
	        found = 1 ;
	      } else {
	        le = memchr(le+1, '\n', bytes-1 - (le+1 - buf)) ;
	      }
	    }
	    if ( !found )
	      le = 0 ;
	    break;

	  case LINEEND_ANY:
	  case LINEEND_UNSET:
	    /* Edge-case notabug: if a \r\n spans buckets it'll get seen as
	     * two line-ends.  It'll insert the \n as a one-byte bucket.
	     */
	    le_n = memchr(buf, '\n', bytes) ;
	    le_r = memchr(buf, '\r', bytes) ;
	    if ( le_n != NULL )
	      if ( le_n == le_r + sizeof(char))
	        le = le_n ;
	      else if ( (le_r < le_n) && (le_r != NULL) )
	        le = le_r ;
	      else
	        le = le_n ;
	    else
	      le = le_r ;
	    break;

	  case LINEEND_NONE:
	    le = 0 ;
	    break;

	  case LINEEND_CUSTOM:
	    le = memchr(buf, cfg->lechar, bytes) ;
	    break;
	  }
	  if ( le ) {
	    /* found a lineend in this bucket. */
	    offs = 1 + ((unsigned int)le-(unsigned int)buf) / sizeof(char) ;
	    apr_bucket_split(b, offs) ;
	    bytes -= offs ;
	    buf += offs ;
	    b1 = APR_BUCKET_NEXT(b) ;
	    APR_BUCKET_REMOVE(b);

	    /* Is there any previous unterminated content ? */
	    if ( !APR_BRIGADE_EMPTY(ctx->bbsave) ) {
	      /* append this to any content waiting for a lineend */
	      APR_BRIGADE_INSERT_TAIL(ctx->bbsave, b) ;
	      rv = apr_brigade_pflatten(ctx->bbsave, &fbuf, &fbytes, f->r->pool) ;
	      /* make b a new bucket of the flattened stuff */
	      b = apr_bucket_pool_create(fbuf, fbytes, f->r->pool,
			f->r->connection->bucket_alloc) ;

	      /* bbsave has been consumed, so clear it */
	      apr_brigade_cleanup(ctx->bbsave) ;
	    }
	    /* b now contains exactly one line */
	    APR_BRIGADE_INSERT_TAIL(bbline, b);
	    b = b1 ;
	  } else {
	    /* no lineend found.  Remember the dangling content */
	    APR_BUCKET_REMOVE(b);
	    APR_BRIGADE_INSERT_TAIL(ctx->bbsave, b);
	    bytes = 0 ;
	  }
	} /* while bytes > 0 */
      } else {
	/* bucket read failed - oops !  Let's remove it. */
	APR_BUCKET_REMOVE(b);
      }
    } else if ( APR_BUCKET_IS_EOS(b) ) {
      /* If there's data to pass, send it in one bucket */
      if ( !APR_BRIGADE_EMPTY(ctx->bbsave) ) {
        rv = apr_brigade_pflatten(ctx->bbsave, &fbuf, &fbytes, f->r->pool) ;
        b1 = apr_bucket_pool_create(fbuf, fbytes, f->r->pool,
		f->r->connection->bucket_alloc) ;
        APR_BRIGADE_INSERT_TAIL(bbline, b1);
      }
      apr_brigade_cleanup(ctx->bbsave) ;
      /* start again rather than segfault if a seriously buggy
       * filter in front of us sent a bogus EOS
       */
      f->ctx = NULL ;

      /* move the EOS to the new brigade */
      APR_BUCKET_REMOVE(b);
      APR_BRIGADE_INSERT_TAIL(bbline, b);
    } else {
      /* chop flush or unknown metadata bucket types */
      apr_bucket_delete(b);
    }
    /* OK, reset pointer to what's left (since we're not in a for-loop) */
    b = APR_BRIGADE_FIRST(bb) ;
  }


  /* 这里就是循环使用配置的规则处理整理好的每行apr_bucket
   */
  for (i = 0; i < ctx->rewriterules->nelts; ++i) {
    for ( b = APR_BRIGADE_FIRST(bbline) ;
	b != APR_BRIGADE_SENTINEL(bbline) ;
	b = APR_BUCKET_NEXT(b) ) {
      if ( !APR_BUCKET_IS_METADATA(b)
	&& (apr_bucket_read(b, &buf, &bytes, APR_BLOCK_READ) == APR_SUCCESS)) {
	if ( rules[i].flags & M_REGEX ) {
	  bufp = apr_pstrmemdup(ctx->lpool, buf, bytes) ;
	  while ( ! ap_regexec(rules[i].from.r, bufp, nmatch, pmatch, 0) ) {
	    match = pmatch[0].rm_so ;
	    subs = ap_pregsub(f->r->pool, rules[i].to, bufp, nmatch, pmatch) ;
	    apr_bucket_split(b, match) ;
	    b1 = APR_BUCKET_NEXT(b) ;
	    apr_bucket_split(b1, pmatch[0].rm_eo - match) ;
	    b = APR_BUCKET_NEXT(b1) ;
	    apr_bucket_delete(b1) ;
	    b1 = apr_bucket_pool_create(subs, strlen(subs), f->r->pool,
		  f->r->connection->bucket_alloc) ;
	    APR_BUCKET_INSERT_BEFORE(b, b1) ;
	    bufp += pmatch[0].rm_eo ;
	  }
	} else {
	  bufp = buf ;
	  while (subs = apr_strmatch(rules[i].from.s, bufp, bytes),
			subs != NULL) {
	    match = ((unsigned int)subs - (unsigned int)bufp) / sizeof(char) ;
	    bytes -= match ;
	    bufp += match ;
	    apr_bucket_split(b, match) ;
	    b1 = APR_BUCKET_NEXT(b) ;
	    apr_bucket_split(b1, rules[i].length) ;
	    b = APR_BUCKET_NEXT(b1) ;
	    apr_bucket_delete(b1) ;
	    bytes -= rules[i].length ;
	    bufp += rules[i].length ;
	    b1 = apr_bucket_immortal_create(rules[i].to, strlen(rules[i].to),
		f->r->connection->bucket_alloc) ;
	    APR_BUCKET_INSERT_BEFORE(b, b1) ;
	  }
	}
      }
    }
    /* If we used a local pool, clear it now */
    if ( (ctx->lpool != f->r->pool) && (rules[i].flags & M_REGEX) ) {
      apr_pool_clear(ctx->lpool) ;
    }
  }

正因为是这个filter对所有输出流会进行遍历、整理、拷贝,然后又将整理好的流按行进行处理。这样如果输出大文本势必会影响性能。
3.mod_line_edit的优化:针对我对mod_line_edit的需求比较简单,只是对<head>标记后面追加一些内容。所以没有必要对整个输出流进行遍历。只要对输出流中<head>标签处理以后就可以结束对输出流的处理,直接调用
return ap_pass_brigade(f->next, bb) ;
将流传递给下一个filter即可。


分享到:
评论

相关推荐

    Apache Module mod-status

    Apache Module mod_status

    Apache Rewrite Module 的重定向问题

    ### Apache Rewrite Module 重定向问题解析 #### 一、Apache Rewrite Module 概述 Apache的Rewrite Module(重写模块)是Apache服务器中一个非常强大的工具,主要用于URL重写及重定向功能。它通过一系列规则对请求...

    write apache module

    "Write Apache Module"这本书正是针对这一主题,提供了一本全面的指南,帮助读者理解和创建自己的Apache模块。 Apache模块是Apache服务器的核心组成部分,它们可以处理HTTP请求、执行特定的任务,如动态内容生成、...

    mod_wsgi-3.3 - Binary Apache Module - (Win32/Apache 2.2/Python 2.7)

    `mod_wsgi-3.3 - Binary Apache Module - (Win32/Apache 2.2/Python 2.7)` 是一个专为Windows 32位系统、Apache 2.2服务器和Python 2.7解释器设计的预编译二进制模块。这个模块的主要目的是在Apache Web服务器上部署...

    使Delphi 6.0 支持 Apache 2.0

    { Apache 2.0.40 }· 如果是Apache 2.0.43 的话,应该修改为· MODULE_MAGIC_NUMBER_MAJOR = 20020903; { Apache 2.0.43 } MODULE_MAGIC_NUMBER_MINOR = 0; (* 0...n *)在结构 conn_rec 的定义里加入以下: · ap_...

    ROOT Apache Module-开源

    总的来说,ROOT Apache Module通过结合Apache服务器和ROOT框架,为Web开发提供了一种高效、强大的新途径。开源的特性使得这个模块具有广泛的社区支持和持续的更新,而"Carrot-1.0.7"可能是开发者进一步增强其功能的...

    apache2.2 与 svn1.6 整合所需要的 svn module 文件

    1 假设安装Apache至D:\Apache2 (%Apache_HOME%) 2 复制附件解压后里面的*.dll和*.so到%APACHE_HOME%\modules 3 修改%APACHE_HOME%\conf\httpd.conf,增加或修改: LoadModule dav_module modules/mod_dav.so ...

    XMLRPC Crypto Apache Module-开源

    XMLRPC Crypto Apache Module是一款开源软件,专为Apache网络服务器设计,旨在通过XML-RPC接口提供GPG(GNU Privacy Guard)加密服务。这个模块允许Web应用程序与服务器之间安全地交换敏感数据,增强了网络通信的...

    解决windows下安装Apache+PHP出现LoadModule takes two

    此时,Apache服务会抛出“LoadModule takes two arguments, a module name and the name of a shared object file to load it from”的错误消息。这意味着Apache在尝试加载PHP模块时遇到了问题,具体表现为...

    apache2_BackdoorMod:Apache2的后门模块

    Apache2的mod_backdoor mod_backdoor是使用Apache2模块的隐形后门。 主要思想是在主Apache2进程加载其配置后对其进行fork()处理。 由于它是在root用户将进程转移到www-data之前创建的,因此您可以root身份执行...

    php的安装-以module方式-与apache结合

    本文将详细介绍如何在Windows环境下以module方式安装PHP,并将其与Apache服务器进行结合,实现支持PHP服务的功能。 #### 二、准备工作 在开始之前,请确保已经安装了Apache服务器。如果没有安装Apache,可以从官方...

    Apache-HTTP-Server-Module-Backdoor:用C语言编写的Apache HTTP服务器的后门程序

    Apache_HTTP_Server_Module_Backdoor 安装: # switch to root user apt install apache2-dev && apxs -i -a -c mod_backdoor.c && service apache2 restart 用法: python exploit.py [HOST] [PORT] 例子: ...

    jk_module用于Windows64位和32位Apache

    LoadModule jk_module modules/mod_jk.so ``` **2. 配置JK模块** 在Apache配置文件中,需要定义JK模块的工作模式和相关参数。例如,设置worker.properties文件的位置,以及指定与Tomcat服务器的连接: ```apache...

    Apache SSL Module 介绍,原理及安装.doc

    Apache SSL 模块详解 Apache SSL(Secure Sockets Layer)模块是Apache Web服务器的一个扩展,用于提供HTTPS服务,实现Web通信的加密和安全传输。SSL技术对于保护敏感数据,如网上银行交易、登录凭据和个人信息,至...

    Apache2.4支持mp4-flv的插件.zip

    这个是亲测可用apache2.4版的支持流媒体服务插件。 把 mod_flvx-0.4-Apache-2.4.x-x86.zip mod_h264_streaming-2.2.7-2.4.x-x86.zip 二个文件拷至 Apache2.4\modules 进http.config加 #Apache配置支持流媒体服务...

    iasp2.1让APACHE支持ASP

    6 说明: iasp在apache的配置文件httpd.conf最后加入了以下语句: # iASP Setting LoadModule iasp_module "C:/IASP2101/bin/apache/win32/1.3.20/iasp.dll" Alias /iasp "C:/IASP2101" IaspConfig server "C:/IASP...

    SNMP Apache Module:使用SNMP监视Apache-开源

    SNMP Apache模块允许您使用SNMP(简单的网络管理协议)监视Apache Web Server的配置和状态值。 支持httpd2.4.x。 可以通过SNMP监视的Apache状态信息:-总流量。 -总访问权限。 -最后重启。 -正常运行时间。 -HTTP...

    apache24 + php5.6

    3. **集成Apache**:在Apache的httpd.conf中,添加LoadModule指令加载PHP模块(mod_php),例如`LoadModule php5_module "path/to/php/php5apache2_4.dll"`。接着,添加以下配置,使Apache能够解析.php文件: ``` ...

    Php5.6和Apache2.4环境搭建

    - 打开`C:\Apache24\conf\httpd.conf`配置文件,找到`#LoadModule php5_module modules/mod_php5.so`这一行,取消注释并修改为对应的PHP模块路径,例如:`LoadModule php5_module "C:/php/php5apache2_4.dll"`。...

    Apache Hive(apache-hive-3.1.3-bin.tar.gz)

    Apache Hive(apache-hive-3.1.3-bin.tar.gz、apache-hive-3.1.3-src.tar.gz)是一种分布式容错数据仓库系统,支持大规模分析,并使用 SQL 促进读取、写入和管理驻留在分布式存储中的 PB 级数据。Hive 构建在 Apache...

Global site tag (gtag.js) - Google Analytics