-
Notifications
You must be signed in to change notification settings - Fork 61
/
cb.php
169 lines (141 loc) · 4.24 KB
/
cb.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<?php
/**
* cb.php
* 只处理\?\?.+的情况
* 部署在项目根目录中
* author: 拔赤 - bachi@taobao.com
*/
//CDN 设置
//$CDN = 'http://a.tbcdn.cn/';
$CDN = 'http://assets.taobaocdn.com/'; //如果是在服务器上配置的话,则打开这一句的注释
//读到-min文件时会转读源文件,这些文件除外
// 新策略的文件转读功能去掉了,没有多少人用
//$exp = '/(editor-min|editor-core-pkg-min|calendar-pkg-min|editor-pkg-min|editor-plugin-pkg-min|kissy-min|simplecalendar-min|sizzle-pkg-min|list-min|base-pkg-min|jstorage-pkg-min)/';
// 线上未找到的文件
$unfound = array();
//抓取文件
function get_contents($url){
$ch =curl_init($url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$str =curl_exec($ch);
curl_close($ch);
if ($str !==false) {
return $str;
}else {
return '';
}
}
//得到扩展名
function get_extend($file_name) {
$extend =explode("." , $file_name);
$va=count($extend)-1;
return $extend[$va];
}
/**
* begin
*/
//cdn上存在的各种可能的文件类型
$header = array(
'js' => 'Content-Type: application/x-javascript',
'css' => 'Content-Type: text/css',
'jpg' => 'Content-Type: image/jpg',
'gif' => 'Content-Type: image/gif',
'png' => 'Content-Type: image/png',
'jpeg' => 'Content-Type: image/jpeg',
'swf' => 'Content-Type: application/x-shockwave-flash'
);
//文件类型
$type = '';
//原始请求文件完整路径数组
$files = array();
//原始请求文件相对路径数组
$tmp_files = array();
//过滤后的文件完整路径数组,即待抓取的文件列表
$a_files = array();
//文件的最后修改时间
$last_modified_time = 0;
//获得当前目录,比如,/home/a.tbcdn.cn/
$pwd = getcwd().'/';
$request_headers = getallheaders();
// 输出结果使用的数组
$R_files = array();
//得到请求的前缀
$prefix = $_SERVER['SCRIPT_NAME'];
// 处理请求中附带的文件列表,得到原始数据
$split_a= explode("??",$_SERVER['REQUEST_URI']);
$tmp_files = explode(",",$split_a[1]);
if(preg_match('/,/',$split_a[1])){
$_tmp = explode(',',$split_a[1]);
foreach($_tmp as $v){
$files[] = $prefix.$v;
}
}else{//单文件
$files[] = $prefix.$split_a[1];
}
// 得到需要读取的文件列表
foreach ($files as $k){
//将开头的/和?去掉
$k = preg_replace(
array('/^\//','/\?.+$/'),
array('',''),
$k);
if(!preg_match('/(\.js|\.css)$/',$k)){
continue;
}
while(preg_match('/[^\/]+\/\.\.\//',$k)){
$k = preg_replace(
array('/[^\/]+\/\.\.\//'),
array(''),
$k,1);
}
$a_files[] = $k;
}
// 得到拼接文件的Last-Modified时间
foreach ($a_files as $k){
if(file_exists($k)){
$filemtime = filemtime($k);
if($filemtime && ($filemtime > $last_modified_time)){
$last_modified_time = $filemtime;
}
}
}
// 检查请求头的if-modified-since
if (isset($request_headers['If-Modified-Since']) &&
(strtotime($request_headers['If-Modified-Since']) == $last_modified_time)) {
// 如果客户端带有缓存
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time.' GMT'), true, 304);
exit;
}
// 拼接文件,并应用通用规则
foreach ($a_files as $k) {
if(empty($type)) {
$type = get_extend($k);
}
//文件存在
if(file_exists($k)) {
$R_files[] = file_get_contents($k);
}else{
//文件不存在
try{
$R_files[] = '/***** combined from productServer: http://a.tbcdn.cn/'.$k.' *****/';
$tfile = file($CDN.$k);
if(!$tfile){
$unfound[] = 'http://a.tbcdn.cn/'.$k;
}
$R_files[] = join('',$tfile);
//如果apache不支持file抓取远程文件,打开这个注释
//$R_files[] = join('', get_contents($CDN.$k));
}catch(Exception $e){}
}
}
header("Expires: " . date("D, j M Y H:i:s", strtotime("now + 10 years")) ." GMT");
header("Cache-Control: max-age=315360000");
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT');
header($header[$type]);
$result = join("\n",$R_files);
echo $result;
echo "/* non published files:\n";
echo join("\n",$unfound);
echo "\n*/";
?>