UNPKG

11.1 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.beforeRes = exports.afterRes = exports.beforeReq = undefined;
7
8var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; //事件触发中心
9
10
11var _log = require('./log');
12
13var _log2 = _interopRequireDefault(_log);
14
15var _rule = require('./config/rule');
16
17var _config = require('./config/config');
18
19var config = _interopRequireWildcard(_config);
20
21var _mime = require('mime');
22
23var _mime2 = _interopRequireDefault(_mime);
24
25var _iconvLite = require('iconv-lite');
26
27var _iconvLite2 = _interopRequireDefault(_iconvLite);
28
29var _zlib = require('zlib');
30
31var _zlib2 = _interopRequireDefault(_zlib);
32
33var _buffer = require('buffer');
34
35var _promise = require('promise');
36
37var _promise2 = _interopRequireDefault(_promise);
38
39var _path = require('path');
40
41var _path2 = _interopRequireDefault(_path);
42
43function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
44
45function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
46
47//<meta charset="gb2312">
48//<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
49var checkMetaCharset = /<meta(?:\s)+.*charset(?:\s)*=(?:[\s'"])*([^"']+)/i;
50//自动解析类型,其他类型一律保存的是 Buffer
51var autoDecodeRegs = /text\/.+|(?:application\/(?:json.*|.*javascript))/i;
52//不解码的后缀格式
53var excludeDecodeExt = ['ttf', 'eot', 'svg', 'woff'];
54//解压数据
55var decodeCompress = function decodeCompress(bodyData, encode) {
56 return new _promise2.default(function (resolve, reject) {
57 //成功的取到bodyData
58 if (bodyData) {
59 var isZip = /gzip/i.test(encode);
60 var isDeflate = /deflate/i.test(encode);
61 if (isZip) {
62 _zlib2.default.gunzip(bodyData, function (err, buff) {
63 if (err) {
64 reject(err.message);
65 _log2.default.error('decompress err: ', err.message);
66 } else {
67 resolve(buff);
68 }
69 });
70 } else if (isDeflate) {
71 _zlib2.default.inflateRaw(bodyData, function (err, buff) {
72 if (err) {
73 reject(err.message);
74 _log2.default.error('decompress err: ', err.message);
75 } else {
76 resolve(buff);
77 }
78 });
79 } else {
80 resolve(bodyData);
81 }
82 } else {
83 resolve(new _buffer.Buffer(""));
84 }
85 });
86};
87
88/**
89 * 代理请求发出前
90 * 该方法主要是处理在响应前的所有事情,可以用来替换header,替换头部数据等操作
91 * 可以直接像res中写数据结束请求
92 * 如果是异步请返回promise对象
93 * @param reqInfo 请求信息 可以修改请求代理的form数据和 请求代理的头部数据
94 * @param {resInfo} 响应投信息可以修改响应投的header
95 * @param res 响应对象
96 * @returns {*}
97 * reqInfo 包含的信息
98 * {
99 * headers: "请求头"
100 * host: "请求地址,包括端口,默认端口省略"
101 * method: "请求方法"
102 * protocol: "请求协议"
103 * originalFullUrl: "原始请求地址,包括参数"
104 * req: "请求对象,请勿删除"
105 * port: "请求端口"
106 * startTime: "请求开始时间"
107 * path: "请求路径,包括参数"
108 * originalUrl: "原始的请求地址,不包括参数,请不要修改",
109 * bodyData: "buffer 数据,body参数,可以修改"
110 * }
111 *
112 * 举例说明,可以请求的修改的地方
113 * 修改请求头,注意只有请求远程服务器的时候管用
114 * reqInfo.headers['test-cjx'] = 111;
115 * //修改请求域名
116 * reqInfo.host = '114.113.198.187';
117 * //修改请求协议
118 * reqInfo.protocol = '114.113.198.187';
119 * //修改请求端口
120 * reqInfo.port="8080"
121 * //修改请求路径--包括get参数
122 * reqInfo.path= "/ccc?aaa"
123 * //修改方法
124 * reqInfo.method= "post" //注意post方法要有对应的content-type数据才能过去
125 * //修改请求数据
126 * reqInfo.bodyData = "请求数据",
127 * //直接定位到某个文件 --如果返回某个文件,有这个,就会忽略远程的调用即host设置之类的都无效
128 * reqInfo.sendToFile
129 * //重定向到某个url,--有这个,就会忽略远程的调用即host设置之类的都无效
130 * reqInfo.redirect
131 */
132var beforeReq = function beforeReq(reqInfo) {
133 // reqInfo.headers['test-cjx'] = 111;
134 // reqInfo.path = '/hyg/mobile/common/base/base.34b37a3c0b.js';
135 // reqInfo.port = 9090;
136 // reqInfo.protocol = "https";
137 // reqInfo.path = "/a/b?c=d";
138 // reqInfo.method = "post";
139 // reqInfo.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
140 // reqInfo.bodyData = new Buffer('a=b&c=d');
141 // reqInfo.sendToFile = "D:/project/gitWork/catproxy/bin.js";
142
143 // log.debug(reqInfo.headers);
144 // log.debug(reqInfo.bodyData.toString());
145 // if (reqInfo.host.indexOf('pimg1.126.net') > -1) {
146 // reqInfo.host = '114.113.198.187';
147 // }
148 return (0, _rule.parseRule)(reqInfo).then(function (result) {
149 return result || reqInfo;
150 }).then(function (reqInfo) {
151 return reqInfo;
152 });
153};
154//如果不是合法的类型,就不进行decode
155var decodeContent = function decodeContent(bodyData, contentType, contentEncoding, isDecode) {
156 //先看看是否需要解压数据
157 return decodeCompress(bodyData, contentEncoding)
158 //解压后在通过编码去解码数据
159 .then(function (bodyData) {
160 //默认编码是utf8
161 var charset = 'UTF-8',
162 tmp = void 0;
163 var ext = _mime2.default.extension(contentType);
164 if (!bodyData || !isDecode) {
165 return { bodyData: bodyData, charset: charset };
166 }
167 if (contentType) {
168 //如果contenttype上又编码,则重新设置编码
169 tmp = contentType.match(/charset=([^;]+)/);
170 if (tmp && tmp.length > 0) {
171 charset = tmp[1].toUpperCase();
172 }
173 }
174 if (_buffer.Buffer.isBuffer(bodyData)) {
175 //其他编码先尝试用 iconv去解码
176 if (charset !== 'UTF-8' && _iconvLite2.default.encodingExists(charset)) {
177 bodyData = _iconvLite2.default.decode(bodyData, charset);
178 } else if (contentType && (ext === 'html' || ext === 'htm')) {
179 //如果是一个文档,在取一次编码
180 var strBodyData = bodyData.toString();
181 //在内容中再次找寻编码
182 var _tmp = strBodyData.match(checkMetaCharset);
183 if (_tmp && _tmp[1]) {
184 _tmp[1] = _tmp[1].toUpperCase();
185 if (_tmp[1] !== "UTF-8" && _iconvLite2.default.encodingExists(_tmp[1])) {
186 charset = _tmp[1];
187 bodyData = _iconvLite2.default.decode(bodyData, _tmp[1]);
188 } else {
189 bodyData = strBodyData;
190 }
191 } else {
192 bodyData = strBodyData;
193 }
194 } else {
195 bodyData = bodyData.toString();
196 }
197 }
198 //再次加编码传递到页面
199 return {
200 bodyData: bodyData,
201 charset: charset
202 };
203 });
204};
205/**
206 * 准备响应请求前
207 * @param {[type]} resInfo [响应信息]
208 * * resInfo包含的信息
209 * {
210 * statusCode: "响应状态码, 可以修改"
211 * headers: "请求头,可修改"
212 * ---注意如果有bodyData则会直接用bodyData的数据返回
213 * bodyData: "buffer 数据",
214 * bodyDataErr: "请求出错,目前如果是大文件会触发这个,这个时候bodyData为空,且不可以设置"
215 * //这个时候 resInfo,bodyData无效
216 * originalFullUrl 原始请求url
217 * originalUrl 原始请求url
218 * }
219 *
220 * 举例说明可以修改响应的地方/
221 * resInfo.headers['test-cjx'] = 111;
222 * @return {[type]} [description]
223 */
224var beforeRes = function beforeRes(resInfo) {
225 return _promise2.default.resolve(resInfo).then(function (resInfo) {
226 //禁用缓存则删掉缓存相关的header
227 var disCache = config.get('disCache');
228 if (disCache) {
229 resInfo.headers['cache-control'] = "no-store";
230 resInfo.headers.expires = "0";
231 delete resInfo.headers.etag;
232 delete resInfo.headers['last-modifed'];
233 }
234 return resInfo;
235 }).then(function (resInfo) {
236 //禁用缓存或者用户这是监听,则需哟啊解码内容返回给用户
237 var disCache = config.get('disCache');
238 //用户监听
239 var useListener = false;
240 if (disCache || useListener) {
241 var _ret = function () {
242 var contentType = resInfo.headers['content-type'] || "";
243 var contentEncoding = resInfo.headers['content-encoding'];
244 //按照指定编码解码内容
245 var ext = _path2.default.extname(resInfo.path.split('?')[0].split('#')[0]) || "";
246 ext = (ext.split('.')[1] || "").toLowerCase();
247 if (excludeDecodeExt.some(function (cur) {
248 return cur === ext;
249 })) {
250 ext = "";
251 }
252 return {
253 v: decodeContent(resInfo.bodyData, contentType, contentEncoding, autoDecodeRegs.test(contentType) && !!ext).then(function (_ref) {
254 var charset = _ref.charset;
255 var bodyData = _ref.bodyData;
256
257 var extension = _mime2.default.extension(contentType);
258 delete resInfo.headers['content-encoding'];
259 //如果访问的是一个html,并且成功截取到这个html的内容
260 if (disCache && contentType && (extension === 'html' || extension === 'htm') && typeof bodyData === 'string') {
261 bodyData = bodyData.replace("<head>", '<head>\n\t\t\t\t\t\t<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />\n\t\t\t\t\t\t<meta http-equiv="Pragma" content="no-cache" />\n\t\t\t\t\t\t<meta http-equiv="Expires" content="0" />');
262 }
263 resInfo.charset = charset;
264 resInfo.bodyData = bodyData;
265 return resInfo;
266 })
267 };
268 }();
269
270 if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
271 }
272 return _promise2.default.resolve(resInfo);
273 }).then(function (resInfo) {
274 //为什么要变成buffer主要是为了让浏览器认识,根据浏览器当前的编码解析
275 if (typeof resInfo.bodyData === 'string') {
276 resInfo.bodyData = _iconvLite2.default.encode(resInfo.bodyData, resInfo.charset || "UTF-8");
277 }
278 return resInfo;
279 });
280 // resInfo.statusCode = 302;
281 // resInfo.headers['test-cjx'] = 111;
282 // bodyData = "test";
283};
284
285/**
286 * 请求响应后
287 * 该方法主要是请求响应后的处理操作,主要是可以查看请求数据,
288 * 注意这时候请求已经结束了,无法在做其他的处理
289 * @param result
290 * 所有字段不可以修改,只可以查看
291 * * result包含的信息
292 * {
293 * statusCode: "响应状态码"
294 * headers: "请求头"
295 * host: "请求地址"
296 * method: "请求方法"
297 * protocol: "请求协议"
298 * originalFullUrl: "原始请求地址,包括参数"
299 * port: "请求端口"
300 * endTime: "请求开始时间"
301 * path: "请求路径,包括参数"
302 * originalUrl: "原始的请求地址,不包括参数",
303 * bodyData: "buffer 数据,body参数",
304 * bodyDataErr: null,
305 * bodyDataFile: null //如果资源定位到本地就显示这个字段
306 * }
307 * @returns {*}
308 */
309var afterRes = function afterRes(result) {
310 return result;
311};
312
313exports.beforeReq = beforeReq;
314exports.afterRes = afterRes;
315exports.beforeRes = beforeRes;
\No newline at end of file