Commit 97e29a30 authored by Antoor's avatar Antoor

Reconstruction of the back-end HTTP request module

重构后端HTTP请求模块
parent c9aaf2a3
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
### /25 ### /25
1. 移除`webpack`以及其他不必要的依赖,直接无需编译即可执行ES6代码(有新模块`babel`的加入,请使用`npm install`初始化 1. 移除`webpack`以及其他不必要的依赖,直接无需编译即可执行ES6代码(有新模块`babel`的加入,请使用`npm install`初始化
2. 更新美化关于页面
3. 重构`modules/request.js`后端数据请求模块
### /24 `(v1.2.1)` ### /24 `(v1.2.1)`
1. 重写前端资源加载方案 1. 重写前端资源加载方案
......
// /**
// Superagent发包模块 * HTTP后端数据发送处理函数
// * 更新: 2016/04/25
*/
'use strict'; 'use strict';
const fs = require('fs'); const fs = require('fs'),
const through = require('through'); iconv = require('iconv-lite'),
const log4js = require('log4js'); logger = require('log4js').getLogger('Request'),
const iconv = require('iconv-lite'); through = require('through'),
const superagent = require('superagent'); superagent = require('superagent'),
superagentProxy = require('superagent-proxy');
const logger = log4js.getLogger('Request'); // 请求UA
const USER_AGENT = 'antSword/v1.3';
var aproxymode = "noproxy"; // 请求超时
var aproxyuri = ""; const REQ_TIMEOUT = 5000;
// 代理配置
const APROXY_CONF = {
mode: 'noproxy',
uri: ''
}
class Request { class Request {
constructor(electron) { constructor(electron) {
// 监听请求
const userAgent = 'antSword/1.1';
const timeout = 5000;
const ipcMain = electron.ipcMain; const ipcMain = electron.ipcMain;
// 代理测试 ipcMain.on('aproxy', this.onAproxy.bind(this));
ipcMain.on('aproxytest', (event, opts) => { ipcMain.on('aproxytest', this.onAproxyTest.bind(this));
var _superagent = require('superagent'); ipcMain.on('request', this.onRequest.bind(this));
var _aproxyuri = opts['aproxyuri']; ipcMain.on('download', this.onDownlaod.bind(this));
logger.debug("[aProxy] Test Proxy - " + _aproxyuri + " - Connect to " + opts['url']); }
require('superagent-proxy')(superagent);
_superagent
.get(opts['url']) /**
.set('User-Agent', userAgent) * 加载代理配置
.proxy(_aproxyuri) * @param {Object} event ipcMain事件
.timeout(timeout) * @param {Object} opts 代理配置
.end((err, ret) => { * @return {[type]} [description]
if (err) { */
logger.debug("[aProxy] Test Error"); onAproxy(event, opts) {
return event.sender.send('aproxytest-error-' + opts['hash'], err); logger.debug(
}else{ 'aProxy::Set Proxy Mode -',
logger.debug("[aProxy] Test Success"); APROXY_CONF['mode'] === 'manualproxy' ? APROXY_CONF['uri'] : 'noproxy'
return event.sender.send('aproxytest-success-' + opts['hash'], ret); );
}
}); APROXY_CONF['mode'] = opts['aproxymode'];
}); APROXY_CONF['uri'] = opts['aproxyuri'];
// 加载代理设置
ipcMain.on('aproxy', (event, opts) => { if (APROXY_CONF['mode'] === 'noproxy') {
aproxymode = opts['aproxymode']; return superagent.Request.prototype.proxy = function() { return this };
aproxyuri = opts['aproxyuri']; }
logger.debug("[aProxy] Set Proxy Mode - " + (aproxymode == "manualproxy" ? aproxyuri : " noproxy")); superagentProxy(superagent);
if (aproxymode == "noproxy") { }
superagent.Request.prototype.proxy=function(arg) {
return this; /**
* 监听代理连接测试
* @param {Object} event ipcMain事件
* @param {Object} opts 测试配置
* @return {[type]} [description]
*/
onAproxyTest(event, opts) {
logger.debug('aProxy::Test Proxy -', opts['aproxyuri'], '- Connect to ', opts['url']);
superagentProxy(superagent);
superagent
.get(opts['url'])
.set('User-Agent', USER_AGENT)
.proxy(opts['aproxyuri'])
.timeout(REQ_TIMEOUT)
.end((err, ret) => {
if (err) {
logger.error("aProxy::Test Error", err);
return event.sender.send('aproxytest-error-' + opts['hash'], err);
}else{
logger.info("aProxy::Test Success");
return event.sender.send('aproxytest-success-' + opts['hash'], ret);
}
});
}
/**
* 监听HTTP请求
* @param {Object} event ipcMain事件对象
* @param {Object} opts 请求配置
* @return {[type]} [description]
*/
onRequest(event, opts) {
logger.debug('onRequest::url', opts['url']);
logger.debug('onRequest::data', opts['data']);
superagent
.post(opts['url'])
.set('User-Agent', USER_AGENT)
.proxy(APROXY_CONF['uri'])
.type('form')
.timeout(REQ_TIMEOUT)
.send(opts['data'])
.parse((res, callback) => {
this.parse(opts['tag_s'], opts['tag_e'], (chunk) => {
event.sender.send('request-chunk-' + opts['hash'], chunk);
}, res, callback);
})
.end((err, ret) => {
if (err) {
return event.sender.send('request-error-' + opts['hash'], err);
}; };
}else{ let buff = ret.body;
require('superagent-proxy')(superagent); // 解码
}; let text = iconv.decode(buff, opts['encode']);
}); // 回调数据
// 监听请求 event.sender.send('request-' + opts['hash'], {
ipcMain.on('request', (event, opts) => { text: text,
logger.debug("[aProxy] Connect mode - " + (aproxymode == "manualproxy" ? aproxyuri : " noproxy")); buff: buff
logger.debug(opts['url'] + '\n', opts['data']);
superagent
.post(opts['url'])
.set('User-Agent', userAgent)
.proxy(aproxyuri)
.type('form')
.timeout(timeout)
.send(opts['data'])
.parse((res, callback) => {
this.parse(opts['tag_s'], opts['tag_e'], (chunk) => {
event.sender.send('request-chunk-' + opts['hash'], chunk);
}, res, callback);
})
.end((err, ret) => {
if (err) {
return event.sender.send('request-error-' + opts['hash'], err);
};
const buff = ret.body;
// 解码
const text = iconv.decode(buff, opts['encode']);
// 回调数据
event.sender.send('request-' + opts['hash'], {
text: text,
buff: buff
});
}); });
}); });
/** }
* 监听文件下载请求
* - 技术实现:通过pipe进行数据流逐步解析,当遇到截断符,则标记,最后数据传输完成,利用标记点进行数据截取,最后保存。 /**
* @opts {Object:path,url,data,tag_s,tag_e} * 监听下载请求
*/ * @param {Object} event ipcMain事件对象
ipcMain.on('download', (event, opts) => { * @param {Object} opts 下载配置
logger.debug('DOWNLOAD', opts); * @return {[type]} [description]
*/
// 创建文件流 onDownlaod(event, opts) {
const rs = fs.createWriteStream(opts['path']); logger.debug('onDownlaod', opts);
let indexStart = -1; // 创建文件流
let indexEnd = -1; const rs = fs.createWriteStream(opts['path']);
let tempData = [];
let indexStart = -1;
// 开始HTTP请求 let indexEnd = -1;
superagent let tempData = [];
.post(opts['url'])
.set('User-Agent', userAgent) // 开始HTTP请求
.proxy(aproxyuri) superagent
.type('form') .post(opts['url'])
// 设置超时会导致文件过大时写入出错 .set('User-Agent', USER_AGENT)
// .timeout(timeout) .proxy(APROXY_CONF['uri'])
.send(opts['data']) .type('form')
.pipe(through( // 设置超时会导致文件过大时写入出错
(chunk) => { // .timeout(timeout)
// 判断数据流中是否包含后截断符?长度++ .send(opts['data'])
let temp = chunk.indexOf(opts['tag_e']); .pipe(through(
if (temp !== -1) { (chunk) => {
indexEnd = Buffer.concat(tempData).length + temp; // 判断数据流中是否包含后截断符?长度++
}; let temp = chunk.indexOf(opts['tag_e']);
tempData.push(chunk); if (temp !== -1) {
event.sender.send('download-progress-' + opts['hash'], chunk.length); indexEnd = Buffer.concat(tempData).length + temp;
}, };
() => { tempData.push(chunk);
let tempDataBuffer = Buffer.concat(tempData); event.sender.send('download-progress-' + opts['hash'], chunk.length);
},
indexStart = tempDataBuffer.indexOf(opts['tag_s']) || 0; () => {
// 截取最后的数据 let tempDataBuffer = Buffer.concat(tempData);
let finalData = new Buffer(tempDataBuffer.slice(
indexStart + opts['tag_s'].length, indexStart = tempDataBuffer.indexOf(opts['tag_s']) || 0;
indexEnd // 截取最后的数据
), 'binary'); let finalData = new Buffer(tempDataBuffer.slice(
// 写入文件流&&关闭 indexStart + opts['tag_s'].length,
rs.write(finalData); indexEnd
rs.close(); ), 'binary');
event.sender.send('download-' + opts['hash'], finalData.length); // 写入文件流&&关闭
// 删除内存数据 rs.write(finalData);
finalData = tempDataBuffer = tempData = null; rs.close();
} event.sender.send('download-' + opts['hash'], finalData.length);
)); // 删除内存数据
}); finalData = tempDataBuffer = tempData = null;
}
));
} }
// 二进制数据流解析 /**
* 二进制数据流解析
* @param {String} tag_s 数据截断符号(前)
* @param {String} tag_e 数据截断符号(后)
* @param {Function} chunkCallBack 数据流回调函数
* @param {Object} res Superagent::res对象
* @param {Function} callback 数据获取完毕回调事件
* @return {[type]} [description]
*/
parse(tag_s, tag_e, chunkCallBack, res, callback) { parse(tag_s, tag_e, chunkCallBack, res, callback) {
// 数据转换二进制处理 // 数据转换二进制处理
res.setEncoding('binary'); res.setEncoding('binary');
......
...@@ -19,9 +19,9 @@ class About { ...@@ -19,9 +19,9 @@ class About {
<hr/> <hr/>
<h2>中国蚁剑</h2> <h2>中国蚁剑</h2>
<p> <p>
<a href="https://github.com/antoor/antSword"><i class="fa fa-github-alt"></i> GitHub</a> | <a href="https://github.com/antoor/antSword"><i class="fa fa-github-alt"></i> GitHub</a> /
<a href="http://uyu.us"><i class="fa fa-home"></i> 主页</a> | <a href="http://uyu.us"><i class="fa fa-home"></i> 主页</a> /
<a href="http://doc.uyu.us"><i class="fa fa-book"></i> 文档</a> | <a href="http://doc.uyu.us"><i class="fa fa-book"></i> 文档</a> /
<a href="http://shang.qq.com/wpa/qunwpa?idkey=51997458a52d534454fd15e901648bf1f2ed799fde954822a595d6794eadc521"><i class="fa fa-qq"></i> Q群</a> <a href="http://shang.qq.com/wpa/qunwpa?idkey=51997458a52d534454fd15e901648bf1f2ed799fde954822a595d6794eadc521"><i class="fa fa-qq"></i> Q群</a>
</p> </p>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment