refactor: 修复关闭代理失败的bug

pull/180/head
xiaojunnuo 2020-11-08 01:45:12 +08:00
parent a392b4c54d
commit 750e444af2
11 changed files with 40 additions and 181 deletions

View File

@ -22,7 +22,7 @@
等你来提issue
## 快速开始
目前仅支持windows
### 1、安装与启动
```shell
git clone https://gitee.com/docmirror/dev-sidecar.git

View File

@ -80,6 +80,12 @@ module.exports = {
'downloads.openwrt.org': { '.*': { proxy: 'openwrt.proxy.ustclug.org' } },
'secure.gravatar.com': { '.*': { proxy: 'gravatar.proxy.ustclug.org' } }
},
whiteList: {
'alipay.com': true,
'*.alipay.com': true,
'pay.weixin.qq.com': true,
'www.baidu.com': true
},
dns: {
providers: {
aliyun: {

View File

@ -87,7 +87,9 @@ module.exports = {
plugins.push(close())
}
}
await Promise.all(plugins)
if (plugins.length > 0) {
await Promise.all(plugins)
}
if (status.proxy.enabled) {
try {

View File

@ -20,7 +20,7 @@ const ProxyPlugin = function (context) {
async unsetProxy () {
try {
shell.setSystemProxy()
await shell.setSystemProxy()
event.fire('status', { key: 'proxy.enabled', vlaue: false })
console.log('关闭系统代理成功')
return true

View File

@ -52,7 +52,6 @@ const serverApi = {
serverProcess.send({ type: 'action', event: { key: 'close' } })
}
}
console.log('fork return pid: ' + serverProcess.pid)
serverProcess.on('message', function (msg) {
console.log('收到子进程消息', msg)
if (msg.type === 'status') {

View File

@ -1,92 +0,0 @@
const interceptors = require('../../../lib/interceptor')
const dnsUtil = require('../../../lib/dns')
const lodash = require('lodash')
function matchHostname (intercepts, hostname) {
const interceptOpts = intercepts[hostname]
if (interceptOpts) {
return interceptOpts
}
if (!interceptOpts) {
for (const target in intercepts) {
if (target.indexOf('*') < 0) {
continue
}
// 正则表达式匹配
if (hostname.match(target)) {
return intercepts[target]
}
}
}
}
function isMatched (url, regexp) {
return url.match(regexp)
}
function domainRegexply (target) {
return target.replace(/\./g, '\\.').replace(/\*/g, '.*')
}
module.exports = (config) => {
const regexpIntercepts = {}
lodash.each(config.intercepts, (value, domain) => {
if (domain.indexOf('*') >= 0) {
const regDomain = domainRegexply(domain)
regexpIntercepts[regDomain] = value
} else {
regexpIntercepts[domain] = value
}
})
const intercepts = regexpIntercepts
const dnsMapping = config.dns.mapping
const serverConfig = config
return {
port: serverConfig.port,
dnsConfig: {
providers: dnsUtil.initDNS(serverConfig.dns.providers),
mapping: dnsMapping
},
sslConnectInterceptor: (req, cltSocket, head) => {
const hostname = req.url.split(':')[0]
return !!matchHostname(intercepts, hostname) // 配置了拦截的域名,将会被代理
},
requestInterceptor: (rOptions, req, res, ssl, next) => {
const hostname = rOptions.hostname
const interceptOpts = matchHostname(intercepts, hostname)
if (!interceptOpts) { // 该域名没有配置拦截器,直接过
next()
return
}
for (const regexp in interceptOpts) { // 遍历拦截配置
const interceptOpt = interceptOpts[regexp]
if (regexp !== true) {
if (!isMatched(req.url, regexp)) {
continue
}
}
for (const interceptImpl of interceptors) {
// 根据拦截配置挑选合适的拦截器来处理
if (!interceptImpl.is(interceptOpt) && interceptImpl.requestInterceptor) {
continue
}
try {
const result = interceptImpl.requestInterceptor(interceptOpt, rOptions, req, res, ssl)
if (result) { // 拦截成功,其他拦截器就不处理了
return
}
} catch (err) {
// 拦截失败
console.error('拦截处理失败',err)
}
}
}
next()
},
responseInterceptor: (req, res, proxyReq, proxyRes, ssl, next) => {
next()
}
}
}

View File

@ -1,67 +0,0 @@
const mitmproxy = require('../../../lib/proxy')
const ProxyOptions = require('./options')
function fireError (e) {
process.send({ type: 'error', event: e })
}
function fireStatus (status) {
process.send({ type: 'status', event: status })
}
let server
function start () {
const config = JSON.parse(process.argv[2])
const proxyOptions = ProxyOptions(config)
const newServer = mitmproxy.createProxy(proxyOptions, () => {
fireStatus(true)
console.log('代理服务已启动127.0.0.1:' + proxyOptions.port)
})
newServer.on('close', () => {
if (server === newServer) {
server = null
fireStatus(false)
}
})
newServer.on('error', (e) => {
console.log('server error', e)
// newServer = null
fireError(e)
})
}
const api = {
async close () {
return new Promise((resolve, reject) => {
if (server) {
server.close((err) => {
if (err) {
console.log('close error', err, ',', err.code, ',', err.message, ',', err.errno)
if (err.code === 'ERR_SERVER_NOT_RUNNING') {
console.log('代理服务关闭成功')
resolve()
return
}
reject(err)
} else {
console.log('代理服务关闭成功')
resolve()
}
})
} else {
console.log('server is null')
fireStatus(false)
resolve()
}
})
}
}
process.on('message', function (msg) {
console.log('child get msg: ' + JSON.stringify(msg))
if (msg.type === 'action') {
api[msg.event.key](msg.event.params)
}
})
// 启动服务
start()

View File

@ -42,8 +42,9 @@ async function _winUnsetProxy (exec) {
_winAsyncRegSet(regKey, 'ProxyEnable', Registry.REG_DWORD, 0),
_winAsyncRegSet(regKey, 'ProxyServer', Registry.REG_SZ, '')
])
await exec([refreshInternetPs], { type: 'ps' })
console.log('代理关闭成功等待refresh')
await exec(refreshInternetPs, { type: 'ps' })
console.log('代理关闭refresh完成')
return true
}
@ -66,7 +67,7 @@ async function _winSetProxy (exec, ip, port) {
_winAsyncRegSet(regKey, 'ProxyOverride', Registry.REG_SZ, lanIpStr)
])
console.log('代理设置成功等待refresh')
await exec([refreshInternetPs])
await exec(refreshInternetPs)
console.log('代理设置refresh完成')
return true
}

View File

@ -37,7 +37,7 @@ class WindowsSystemShell extends SystemShell {
static async exec (cmds, args = { }) {
let { type } = args
type = type || 'ps'
if (cmds instanceof String) {
if (typeof cmds === 'string') {
cmds = [cmds]
}
if (type === 'ps') {

View File

@ -30,7 +30,7 @@ function registerProcessListener () {
// console.error(err.errno)
return
}
console.error(err)
console.error('uncaughtException:', err)
})
process.on('unhandledRejection', (reason, p) => {

View File

@ -1,19 +1,19 @@
const interceptors = require('./lib/interceptor')
const dnsUtil = require('./lib/dns')
const lodash = require('lodash')
function matchHostname (intercepts, hostname) {
const interceptOpts = intercepts[hostname]
if (interceptOpts) {
return interceptOpts
function matchHostname (hostMap, hostname) {
const value = hostMap[hostname]
if (value) {
return value
}
if (!interceptOpts) {
for (const target in intercepts) {
if (!value) {
for (const target in hostMap) {
if (target.indexOf('*') < 0) {
continue
}
// 正则表达式匹配
if (hostname.match(target)) {
return intercepts[target]
return hostMap[target]
}
}
}
@ -27,18 +27,23 @@ function domainRegexply (target) {
return target.replace(/\./g, '\\.').replace(/\*/g, '.*')
}
module.exports = (config) => {
const regexpIntercepts = {}
lodash.each(config.intercepts, (value, domain) => {
function domainMapRegexply (hostMap) {
const regexpMap = {}
lodash.each(hostMap, (value, domain) => {
if (domain.indexOf('*') >= 0) {
const regDomain = domainRegexply(domain)
regexpIntercepts[regDomain] = value
regexpMap[regDomain] = value
} else {
regexpIntercepts[domain] = value
regexpMap[domain] = value
}
})
return regexpMap
}
module.exports = (config) => {
const intercepts = domainMapRegexply(config.intercepts)
const whiteList = domainMapRegexply(config.whiteList)
const intercepts = regexpIntercepts
const dnsMapping = config.dns.mapping
const serverConfig = config
@ -50,6 +55,11 @@ module.exports = (config) => {
},
sslConnectInterceptor: (req, cltSocket, head) => {
const hostname = req.url.split(':')[0]
const inWhiteList = matchHostname(whiteList, hostname) != null
if (inWhiteList) {
console.log('白名单域名,不拦截', hostname)
return false
}
return !!matchHostname(intercepts, hostname) // 配置了拦截的域名,将会被代理
},
requestInterceptor: (rOptions, req, res, ssl, next) => {