mirror of
https://github.com/alibaba/anyproxy.git
synced 2025-04-20 17:24:21 +00:00
353 lines
8.1 KiB
JavaScript
353 lines
8.1 KiB
JavaScript
/* eslint prefer-arrow-callback: 0 */
|
|
/**
|
|
* An util to make the request out
|
|
*
|
|
*/
|
|
const request = require('request');
|
|
const fs = require('fs');
|
|
const WebSocket = require('ws');
|
|
const HttpsProxyAgent = require('https-proxy-agent');
|
|
const stream = require('stream');
|
|
|
|
const PROXY_HOST = 'http://localhost:8001';
|
|
const SOCKET_PROXY_HOST = 'http://localhost:8001';
|
|
|
|
|
|
const HTTP_SERVER_BASE = 'http://localhost:3000';
|
|
const HTTPS_SERVER_BASE = 'https://localhost:3001';
|
|
const WS_SERVER_BASE = 'ws://localhost:3000';
|
|
const WSS_SERVER_BASE = 'wss://localhost:3001';
|
|
const DEFAULT_CHUNK_COLLECT_THRESHOLD = 20 * 1024 * 1024; // about 20 mb
|
|
|
|
class commonStream extends stream.Readable {
|
|
constructor(config) {
|
|
super({
|
|
highWaterMark: DEFAULT_CHUNK_COLLECT_THRESHOLD * 5
|
|
});
|
|
}
|
|
_read(size) {}
|
|
}
|
|
|
|
function getHostFromUrl(url = '') {
|
|
const hostReg = /^(https{0,1}:\/\/)(\w+)/;
|
|
const match = url.match(hostReg);
|
|
|
|
return match && match[2] ? match[2] : '';
|
|
}
|
|
|
|
function getPortFromUrl(url = '') {
|
|
const portReg = /^https{0,1}:\/\/\w+(:(\d+)){0,1}/;
|
|
const match = url.match(portReg);
|
|
let port = match && match[2] ? match[2] : '';
|
|
|
|
if (!port) {
|
|
port = url.indexOf('https://') === 0 ? 443 : 80;
|
|
}
|
|
return port;
|
|
}
|
|
|
|
/**
|
|
* 获取url中的path
|
|
*/
|
|
function getPathFromUrl(url = '') {
|
|
const pathReg = /^https{0,1}:\/\/\w+(:\d+){0,1}(.+)/;
|
|
const match = url.match(pathReg);
|
|
const path = match && match[3] ? match[2] : url;
|
|
return path;
|
|
}
|
|
|
|
function proxyRequest(method = 'GET', url, params, headers = {}) {
|
|
return doRequest(method, url, params, headers, true);
|
|
}
|
|
|
|
/*
|
|
* 直接请求到真实服务器,不经过代理服务器
|
|
*
|
|
*/
|
|
function directRequest(method = 'GET', url, params, headers = {}) {
|
|
return doRequest(method, url, params, headers);
|
|
}
|
|
|
|
function directUpload(url, filepath, formParams = {}, headers = {}) {
|
|
return doUpload(url, 'POST', filepath, formParams, headers);
|
|
}
|
|
|
|
function proxyUpload(url, filepath, formParams = {}, headers = {}) {
|
|
return doUpload(url, 'POST', filepath, formParams, headers, true);
|
|
}
|
|
|
|
function directPutUpload(url, filepath, formParams = {}, headers = {}) {
|
|
return doUpload(url, 'PUT', filepath, formParams, headers);
|
|
}
|
|
|
|
function proxyPutUpload(url, filepath, headers = {}) {
|
|
return doUpload(url, 'PUT', filepath, headers, true);
|
|
}
|
|
|
|
/**
|
|
* @param params {String} json类型或file路径
|
|
* {Object} key-value形式
|
|
*/
|
|
function doRequest(method = 'GET', url, params, headers = {}, isProxy) {
|
|
headers = Object.assign({}, headers);
|
|
|
|
let reqStream = new commonStream();
|
|
const requestData = {
|
|
headers,
|
|
followRedirect: false,
|
|
rejectUnauthorized: false
|
|
};
|
|
|
|
if (isProxy) {
|
|
requestData.proxy = PROXY_HOST;
|
|
requestData.headers['via-proxy'] = 'true';
|
|
}
|
|
|
|
const streamReq = (resolve, reject) => {
|
|
requestData.headers['content-type'] = 'text/plain'; //otherwise, koa-body could not recognize
|
|
if (typeof params === 'string') {
|
|
fs.existsSync(params) ?
|
|
reqStream = fs.createReadStream(params) :
|
|
reqStream.push(params);
|
|
} else if (typeof params === 'object') {
|
|
reqStream.push(JSON.stringify(params));
|
|
}
|
|
reqStream.push(null);
|
|
reqStream.pipe(request[method.toLowerCase()](
|
|
url,
|
|
requestData,
|
|
(error, response, body) => {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
resolve(response);
|
|
}
|
|
}
|
|
))
|
|
}
|
|
const commonReq = (resolve, reject) => {
|
|
requestData.url = url;
|
|
requestData.method = method;
|
|
requestData.qs = params;
|
|
request(
|
|
requestData,
|
|
(error, response, body) => {
|
|
if (error) {
|
|
reject(error);
|
|
} else {
|
|
resolve(response);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
const requestTask = new Promise((resolve, reject) => {
|
|
if (method === 'POST' || method === 'PUT') {
|
|
streamReq(resolve, reject);
|
|
} else {
|
|
commonReq(resolve, reject);
|
|
}
|
|
});
|
|
return requestTask;
|
|
}
|
|
|
|
|
|
function doUpload(url, method, filepath, formParams, headers = {}, isProxy) {
|
|
let formData = {
|
|
file: fs.createReadStream(filepath)
|
|
};
|
|
|
|
formData = Object.assign({}, formData, formParams);
|
|
headers = Object.assign({}, headers);
|
|
|
|
const requestData = {
|
|
formData,
|
|
url,
|
|
method,
|
|
headers,
|
|
json: true,
|
|
rejectUnauthorized: false
|
|
};
|
|
|
|
if (isProxy) {
|
|
requestData.proxy = PROXY_HOST;
|
|
requestData.headers['via-proxy'] = 'true';
|
|
}
|
|
const requestTask = new Promise((resolve, reject) => {
|
|
request(
|
|
requestData,
|
|
(error, response, body) => {
|
|
if (error) {
|
|
reject(error);
|
|
return;
|
|
}
|
|
resolve(response);
|
|
}
|
|
);
|
|
});
|
|
return requestTask;
|
|
}
|
|
|
|
function doWebSocket(url, isProxy) {
|
|
let ws;
|
|
if (isProxy) {
|
|
const agent = new HttpsProxyAgent(SOCKET_PROXY_HOST);
|
|
ws = new WebSocket(url, {
|
|
agent,
|
|
rejectUnauthorized: false
|
|
});
|
|
} else {
|
|
ws = new WebSocket(url, {
|
|
rejectUnauthorized: false
|
|
});
|
|
}
|
|
|
|
return ws;
|
|
}
|
|
|
|
function proxyGet(url, params, headers = {}) {
|
|
return proxyRequest('GET', url, params, headers);
|
|
}
|
|
|
|
function proxyPost(url, params, headers = {}) {
|
|
return proxyRequest('POST', url, params, headers);
|
|
}
|
|
|
|
function proxyPut(url, params, headers = {}) {
|
|
return proxyRequest('PUT', url, params, headers);
|
|
}
|
|
|
|
function proxyDelete(url, params, headers = {}) {
|
|
return proxyRequest('DELETE', url, params, headers);
|
|
}
|
|
|
|
function proxyHead(url, headers = {}) {
|
|
return proxyRequest('HEAD', url, {}, headers);
|
|
}
|
|
|
|
function proxyOptions(url, headers = {}) {
|
|
return proxyRequest('OPTIONS', url, {}, headers);
|
|
}
|
|
|
|
function directGet(url, params, headers = {}) {
|
|
return directRequest('GET', url, params, headers);
|
|
}
|
|
|
|
function directPost(url, params, headers = {}) {
|
|
return directRequest('POST', url, params, headers);
|
|
}
|
|
|
|
function directPut(url, params, headers = {}) {
|
|
return directRequest('PUT', url, params, headers);
|
|
}
|
|
|
|
function directDelete(url, params, headers = {}) {
|
|
return directRequest('DELETE', url, params, headers);
|
|
}
|
|
|
|
function directHead(url, headers = {}) {
|
|
return directRequest('HEAD', url, {}, headers);
|
|
}
|
|
|
|
function directOptions(url, headers = {}) {
|
|
return directRequest('OPTIONS', url, {}, headers);
|
|
}
|
|
|
|
function proxyWs(url) {
|
|
return doWebSocket(url, true);
|
|
}
|
|
|
|
function directWs(url) {
|
|
return doWebSocket(url);
|
|
}
|
|
|
|
/**
|
|
* generate the final url based on protocol and path
|
|
*
|
|
*/
|
|
function generateUrl(protocol, urlPath) {
|
|
return protocol === 'http' ? HTTP_SERVER_BASE + urlPath : HTTPS_SERVER_BASE + urlPath;
|
|
}
|
|
|
|
function generateWsUrl(protocol, urlPath) {
|
|
return protocol === 'wss' ? WSS_SERVER_BASE + urlPath : WS_SERVER_BASE + urlPath;
|
|
}
|
|
|
|
/*
|
|
* verify if the request data is a valid proxy request, by checking specified header
|
|
*/
|
|
function isViaProxy(req) {
|
|
return req.headers['via-proxy'] === 'true';
|
|
}
|
|
|
|
/*
|
|
* check if url is supported by request moudle
|
|
*/
|
|
function isSupportedProtocol(requestPath) {
|
|
return requestPath.indexOf('http://') === 0 || requestPath.indexOf('https://') === 0;
|
|
}
|
|
|
|
/*
|
|
* collect all request data in one url
|
|
*/
|
|
function getRequestListFromPage(pageUrl, cb) {
|
|
let _ph;
|
|
let _page;
|
|
let _outObj;
|
|
const phantom = require('phantom');
|
|
console.log(`collecting requests from ${pageUrl}...`);
|
|
return phantom.create().then(ph => {
|
|
_ph = ph;
|
|
return _ph.createPage();
|
|
}).then(page => {
|
|
_page = page;
|
|
_outObj = _ph.createOutObject();
|
|
_outObj.urls = [];
|
|
page.property('onResourceRequested', function (requestData, networkRequest, out) {
|
|
out.urls.push(requestData);
|
|
}, _outObj);
|
|
return _page.open(pageUrl);
|
|
})
|
|
.then(status => _outObj.property('urls'))
|
|
.then(urls => {
|
|
_page.close();
|
|
_ph.exit();
|
|
return urls;
|
|
})
|
|
.catch((err) => {
|
|
console.log(`failed to collecting requests from ${pageUrl}`);
|
|
console.log(err);
|
|
});
|
|
}
|
|
|
|
|
|
module.exports = {
|
|
getHostFromUrl,
|
|
getPathFromUrl,
|
|
getPortFromUrl,
|
|
proxyGet,
|
|
proxyPost,
|
|
directGet,
|
|
directPost,
|
|
directUpload,
|
|
proxyUpload,
|
|
generateUrl,
|
|
proxyWs,
|
|
directWs,
|
|
generateWsUrl,
|
|
directPut,
|
|
proxyPut,
|
|
directDelete,
|
|
proxyDelete,
|
|
directHead,
|
|
proxyHead,
|
|
directOptions,
|
|
proxyOptions,
|
|
directPutUpload,
|
|
proxyPutUpload,
|
|
isViaProxy,
|
|
getRequestListFromPage,
|
|
directRequest,
|
|
proxyRequest,
|
|
isSupportedProtocol
|
|
};
|