写了一个apache 的插件模块,用于合并静态文件下载

a.js

b.js

c.js

合并为 ??a.js,b.js,c.js

减少http 请求,并且不影响 mod_expires, gzip 模块的功能

#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "ap_config.h"
#include "apr_buckets.h"
#include "apr_general.h"
#include "apr_lib.h"
#include "http_request.h"

struct m_fileinfo{
	apr_file_t *file;
	apr_off_t size;
};


/* The sample content handler */
static int mergerdownload_handler(request_rec *r)
{
	char *get=NULL;
	char *param=NULL;
	char *tmp=NULL;
	char *fname=NULL;

    if (strcmp(r->handler, "mergerdownload")) {
        return DECLINED;
    }

	//not allow sub request
	if( r->main ){
        return DECLINED;
	}

    if (!r->header_only){
		//GET /css??a.css,b.css,c.css HTTP/1.1
		//GET /js??a.js,b.js,c.js HTTP/1.1
		//valid url 
		if( !(strlen(r->content_type) == 20 && strcmp(r->content_type, "httpd/unix-directory") == 0 && 
					r->args != NULL && *(r->args) == '?') ){			
			return DECLINED;
		}

		get = r->the_request+5;
		param = strstr(get, "??");
		if( param != NULL ){

			apr_finfo_t finfo ;
			apr_file_t* file = NULL ;
			apr_bucket *bucket = NULL;
			apr_size_t fsize;
			apr_bucket_brigade *fcs = apr_brigade_create(r->pool, r->connection->bucket_alloc);
			apr_status_t status;
			apr_time_t modified=0;
			apr_time_t request_m=0;
			char *request_time;
			char *timestr;
			char *arg=NULL;
			param+=2;
			tmp = param;

			//only support .css .js
			if( NULL != strstr(get, ".css") ){				
				r->content_type = "text/css";      
			}else if( NULL != strstr(get, ".js")){
				r->content_type = "application/javascript";      
			}else{
				return DECLINED;			
			}
			int end = 0;
			int filenumber = 0;
			int alloc_file = 10;
			struct m_fileinfo *fileinfo = malloc( sizeof(struct m_fileinfo) * alloc_file );
			if( fileinfo == NULL ){
				return DECLINED;				
			}
			struct m_fileinfo *tmpfile;
			struct m_fileinfo *refileinfo;
			do{
				//get first char ? address
				if( *param == '?' && arg == NULL){
					arg = param;
				}
				if( *param == ',' || *param == ' ' ){

					fname = apr_pstrcat(r->pool, r->filename ,apr_pstrndup( r->pool, (const char *)tmp, (arg!=NULL?arg:param)-tmp ), NULL);
					if( arg != NULL ){
						arg = NULL;
					}
					if( *param == ' ' ){
						end  = 1;
					}else{					
						tmp = param+1;
					}
					if ( (status = apr_stat(&finfo, fname, APR_FINFO_SIZE, r->pool)) == APR_SUCCESS && finfo.filetype != APR_DIR ) {
						if ( apr_file_open(&file, fname, APR_READ|APR_SHARELOCK|APR_SENDFILE_ENABLED,
										APR_OS_DEFAULT, r->pool ) == APR_SUCCESS ) {
							if( file ){
								++filenumber;
								if( filenumber > alloc_file ){
									alloc_file*=2;
									refileinfo = realloc(fileinfo, sizeof(struct m_fileinfo)*alloc_file);
									if( refileinfo == NULL ){										
										free(fileinfo);
										return DECLINED;
									}
									fileinfo = refileinfo;
								}
								tmpfile = (fileinfo+(filenumber-1));
								tmpfile->file = file;
								tmpfile->size = finfo.size;
								modified = finfo.mtime>modified?finfo.mtime:modified;								
							}
						}
					}					
				}
				++param;
			}while( end == 0 );

			apr_pool_cleanup_register(r->pool, fileinfo, free, apr_pool_cleanup_null);
			if( modified > 0 ){
				request_time = apr_table_get(r->headers_in, "If-Modified-Since");
				timestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
				apr_rfc822_date(timestr, modified);
				if( request_time != NULL && strcmp(request_time, timestr) == 0  ){					
					return HTTP_NOT_MODIFIED;
				}
				int n = 0;
				for(n; n<filenumber; n++){
					tmpfile = (fileinfo+n);
					APR_BRIGADE_INSERT_TAIL(fcs, apr_bucket_file_create(tmpfile->file, 0, tmpfile->size, r->pool,r->connection->bucket_alloc));	
				}
				apr_table_setn(r->headers_out, "Last-Modified", timestr);
			}
			bucket  = apr_bucket_eos_create(r->connection->bucket_alloc);
			APR_BRIGADE_INSERT_TAIL(fcs, bucket);
			return ap_pass_brigade(r->output_filters, fcs);
		}else{
			return DECLINED;			
		}
	}
    return OK;
}

static void mergerdownload_register_hooks(apr_pool_t *p)
{
    ap_hook_handler(mergerdownload_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

/* Dispatch list for API hooks */
module AP_MODULE_DECLARE_DATA mergerdownload_module = {
    STANDARD20_MODULE_STUFF, 
    NULL,                  /* create per-dir    config structures */
    NULL,                  /* merge  per-dir    config structures */
    NULL,                  /* create per-server config structures */
    NULL,                  /* merge  per-server config structures */
    NULL,                  /* table of config file commands       */
    mergerdownload_register_hooks  /* register hooks                      */
};


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值