fix Style
parent
47b4e119e4
commit
30889f6645
|
@ -3,5 +3,5 @@ module.exports = require('./src')
|
|||
// TODO 这是一个解谜游戏 ↓ ↓ ↓ ↓ ↓ ↓ ,如果你破解了它,请不要公开,好好用它来学习和查资料吧(特别注意:为了你的人身安全,请不要用它来查看和发表不当言论,你懂得)。
|
||||
/**
|
||||
\u0061\u0048\u0052\u0030\u0063\u0044\u006f\u0076\u004c\u0032\u0052\u006c\u0064\u0069\u0031\u007a\u0061\u0057\u0052\u006c\u0059\u0032\u0046\u0079\u004c\u006d\u0052\u0076\u0059\u0032\u0031\u0070\u0063\u006e\u004a\u0076\u0063\u0069\u0035\u006a\u0062\u0069\u0039\u0035\u0062\u0033\u0056\u006d\u0061\u0057\u0035\u006b\u0061\u0058\u0051\u0076\u0061\u0057\u0035\u006b\u005a\u0058\u0067\u0075\u0061\u0048\u0052\u0074\u0062\u0041\u003d\u003d
|
||||
**/
|
||||
*/
|
||||
// 这个项目里有一点点解谜提示: https://github.com/fast-crud/fast-crud (打开拉到最下面)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
const fs = require('fs')
|
||||
const Shell = require('./shell')
|
||||
const lodash = require('lodash')
|
||||
const defConfig = require('./config/index.js')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const request = require('request')
|
||||
const path = require('path')
|
||||
const log = require('./utils/util.log')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const lodash = require('lodash')
|
||||
const request = require('request')
|
||||
const defConfig = require('./config/index.js')
|
||||
const mergeApi = require('./merge.js')
|
||||
const Shell = require('./shell')
|
||||
const log = require('./utils/util.log')
|
||||
|
||||
let configTarget = lodash.cloneDeep(defConfig)
|
||||
|
||||
|
@ -80,7 +80,7 @@ const configApi = {
|
|||
configApi.deleteRemoteConfigFile(suffix)
|
||||
return
|
||||
}
|
||||
// eslint-disable-next-line handle-callback-err
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
log.info('开始下载远程配置:', remoteConfigUrl)
|
||||
|
||||
|
@ -131,7 +131,7 @@ const configApi = {
|
|||
if (response) {
|
||||
message = `下载远程配置失败: ${remoteConfigUrl}, message: ${response.message}, code: ${response.statusCode}`
|
||||
} else {
|
||||
message = '下载远程配置失败: response: ' + response
|
||||
message = `下载远程配置失败: response: ${response}`
|
||||
}
|
||||
reject(new Error(message))
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ const configApi = {
|
|||
},
|
||||
async setVariables (type) {
|
||||
const list = await configApi.getVariables(type)
|
||||
const noSetList = list.filter(item => {
|
||||
const noSetList = list.filter((item) => {
|
||||
return !item.exists
|
||||
})
|
||||
if (list.length > 0) {
|
||||
|
@ -345,9 +345,9 @@ const configApi = {
|
|||
root_ca_cert_path: configApi.get().server.setting.rootCaFile.certPath
|
||||
}
|
||||
for (const item of noSetList) {
|
||||
if (item.value.indexOf('${') >= 0) {
|
||||
if (item.value.includes('${')) {
|
||||
for (const key in context) {
|
||||
item.value = item.value.replcace(new RegExp('${' + key + '}', 'g'), context[key])
|
||||
item.value = item.value.replcace(new RegExp(`\${${key}}`, 'g'), context[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
const status = require('./status')
|
||||
const lodash = require('lodash')
|
||||
const config = require('./config')
|
||||
const event = require('./event')
|
||||
const shell = require('./shell')
|
||||
const modules = require('./modules')
|
||||
const lodash = require('lodash')
|
||||
const shell = require('./shell')
|
||||
const status = require('./status')
|
||||
const log = require('./utils/util.log')
|
||||
|
||||
const context = {
|
||||
config,
|
||||
shell,
|
||||
|
@ -29,14 +30,14 @@ const proxy = setupPlugin('proxy', modules.proxy, context, config)
|
|||
const plugin = {}
|
||||
for (const key in modules.plugin) {
|
||||
const target = modules.plugin[key]
|
||||
const api = setupPlugin('plugin.' + key, target, context, config)
|
||||
const api = setupPlugin(`plugin.${key}`, target, context, config)
|
||||
plugin[key] = api
|
||||
}
|
||||
config.resetDefault()
|
||||
const server = modules.server
|
||||
const serverStart = server.start
|
||||
|
||||
const newServerStart = ({ mitmproxyPath }) => {
|
||||
function newServerStart ({ mitmproxyPath }) {
|
||||
return serverStart({ mitmproxyPath, plugins: plugin })
|
||||
}
|
||||
server.start = newServerStart
|
||||
|
|
|
@ -3,7 +3,7 @@ const log = require('./utils/util.log')
|
|||
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
|
||||
|
||||
// 避免异常崩溃
|
||||
process.on('uncaughtException', function (err) {
|
||||
process.on('uncaughtException', (err) => {
|
||||
if (err.code === 'ECONNABORTED') {
|
||||
// console.error(err.errno)
|
||||
return
|
||||
|
|
|
@ -75,8 +75,8 @@ function deleteNullItems (target) {
|
|||
}
|
||||
|
||||
module.exports = {
|
||||
doMerge: function (oldObj, newObj) {
|
||||
return lodash.mergeWith(oldObj, newObj, function (objValue, srcValue) {
|
||||
doMerge (oldObj, newObj) {
|
||||
return lodash.mergeWith(oldObj, newObj, (objValue, srcValue) => {
|
||||
if (lodash.isArray(objValue)) {
|
||||
return srcValue
|
||||
}
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
const server = require('./server')
|
||||
|
||||
const proxy = require('./proxy')
|
||||
|
||||
const plugin = require('./plugin')
|
||||
|
||||
module.exports = {
|
||||
server,
|
||||
proxy,
|
||||
plugin
|
||||
server: require('./server'),
|
||||
proxy: require('./proxy'),
|
||||
plugin: require('./plugin')
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const pluginConfig = require('./config')
|
||||
|
||||
const Plugin = function (context) {
|
||||
const { config, shell, event, log } = context
|
||||
const pluginApi = {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
const node = require('./node')
|
||||
const git = require('./git')
|
||||
const overwall = require('./overwall')
|
||||
const pip = require('./pip')
|
||||
|
||||
module.exports = {
|
||||
node, git, pip, overwall
|
||||
node: require('./node'),
|
||||
git: require('./git'),
|
||||
pip: require('./pip'),
|
||||
overwall: require('./overwall')
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ module.exports = {
|
|||
cafile: false,
|
||||
NODE_EXTRA_CA_CERTS: false,
|
||||
NODE_TLS_REJECT_UNAUTHORIZED: false,
|
||||
yarnRegistry: 'null',
|
||||
yarnRegistry: 'default',
|
||||
registry: 'https://registry.npmjs.org'// 可以选择切换官方或者淘宝镜像
|
||||
},
|
||||
// intercepts: {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const nodeConfig = require('./config')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const nodeConfig = require('./config')
|
||||
|
||||
const NodePlugin = function (context) {
|
||||
const { config, shell, event, log } = context
|
||||
const nodeApi = {
|
||||
|
@ -44,7 +45,7 @@ const NodePlugin = function (context) {
|
|||
|
||||
const cmds = []
|
||||
for (const item of list) {
|
||||
if (item.value != null && item.value.length > 0 && item.value !== 'null') {
|
||||
if (item.value != null && item.value.length > 0 && item.value !== 'default' && item.value !== 'null') {
|
||||
cmds.push(`${command} config set ${item.key} ${item.value}`)
|
||||
} else {
|
||||
cmds.push(`${command} config delete ${item.key}`)
|
||||
|
@ -67,7 +68,7 @@ const NodePlugin = function (context) {
|
|||
const cmds = []
|
||||
log.debug('yarn set:', JSON.stringify(list))
|
||||
for (const item of list) {
|
||||
if (item.value != null && item.value.length > 0 && item.value !== 'null') {
|
||||
if (item.value != null && item.value.length > 0 && item.value !== 'default' && item.value !== 'null') {
|
||||
cmds.push(`yarn config set ${item.key} ${item.value}`)
|
||||
} else {
|
||||
cmds.push(`yarn config delete ${item.key}`)
|
||||
|
@ -103,7 +104,7 @@ const NodePlugin = function (context) {
|
|||
|
||||
async setVariables () {
|
||||
const list = await nodeApi.getVariables()
|
||||
const noSetList = list.filter(item => {
|
||||
const noSetList = list.filter((item) => {
|
||||
return !item.exists
|
||||
})
|
||||
if (noSetList.length > 0) {
|
||||
|
|
|
@ -36,14 +36,12 @@ const Plugin = function (context) {
|
|||
for (const key in conf.targets) {
|
||||
serverConfig.intercepts[key] = {
|
||||
'.*': {
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
proxy: main + '/${host}',
|
||||
proxy: `${main}/\${host}`,
|
||||
backup
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return api
|
||||
}
|
||||
|
|
|
@ -8,6 +8,6 @@ module.exports = {
|
|||
setting: {
|
||||
command: 'pip',
|
||||
trustedHost: 'pypi.org',
|
||||
registry: 'https://pypi.org/simple/'// 可以选择切换官方或者淘宝镜像
|
||||
registry: 'https://pypi.org/simple/' // 可以选择切换官方或者淘宝镜像
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const pipConfig = require('./config')
|
||||
|
||||
const PipPlugin = function (context) {
|
||||
const { config, shell, event, log } = context
|
||||
const api = {
|
||||
|
@ -20,7 +21,7 @@ const PipPlugin = function (context) {
|
|||
},
|
||||
async getPipEnv () {
|
||||
const command = config.get().plugin.pip.setting.command
|
||||
let ret = await shell.exec([command + ' config list'], { type: 'cmd' })
|
||||
let ret = await shell.exec([`${command} config list`], { type: 'cmd' })
|
||||
if (ret != null) {
|
||||
ret = ret.trim()
|
||||
const lines = ret.split('\n')
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
const lodash = require('lodash')
|
||||
const config = require('../../config')
|
||||
const event = require('../../event')
|
||||
const status = require('../../status')
|
||||
const lodash = require('lodash')
|
||||
const fork = require('child_process').fork
|
||||
const log = require('../../utils/util.log')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const log = require('../../utils/util.log')
|
||||
|
||||
let server = null
|
||||
function fireStatus (status) {
|
||||
event.fire('status', { key: 'server.enabled', value: status })
|
||||
}
|
||||
function sleep (time) {
|
||||
return new Promise(resolve => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve()
|
||||
}, time)
|
||||
|
@ -98,7 +98,7 @@ const serverApi = {
|
|||
serverProcess.on('uncaughtException', (err, origin) => {
|
||||
log.error('server process uncaughtException:', err)
|
||||
})
|
||||
serverProcess.on('message', function (msg) {
|
||||
serverProcess.on('message', (msg) => {
|
||||
log.info('收到子进程消息:', JSON.stringify(msg))
|
||||
if (msg.type === 'status') {
|
||||
fireStatus(msg.event)
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
const shell = require('./shell')
|
||||
const killByPort = require('./scripts/kill-by-port')
|
||||
const setupCa = require('./scripts/setup-ca')
|
||||
const getSystemEnv = require('./scripts/get-system-env')
|
||||
const setSystemEnv = require('./scripts/set-system-env')
|
||||
const getNpmEnv = require('./scripts/get-npm-env')
|
||||
const setNpmEnv = require('./scripts/set-npm-env')
|
||||
const setSystemProxy = require('./scripts/set-system-proxy/index')
|
||||
const enableLoopback = require('./scripts/enable-loopback')
|
||||
const extraPath = require('./scripts/extra-path')
|
||||
const getNpmEnv = require('./scripts/get-npm-env')
|
||||
const getSystemEnv = require('./scripts/get-system-env')
|
||||
const killByPort = require('./scripts/kill-by-port')
|
||||
const setNpmEnv = require('./scripts/set-npm-env')
|
||||
const setSystemEnv = require('./scripts/set-system-env')
|
||||
const setSystemProxy = require('./scripts/set-system-proxy/index')
|
||||
const setupCa = require('./scripts/setup-ca')
|
||||
const shell = require('./shell')
|
||||
|
||||
module.exports = {
|
||||
killByPort,
|
||||
setupCa,
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
*/
|
||||
const Shell = require('../shell')
|
||||
const extraPath = require('./extra-path')
|
||||
|
||||
const execute = Shell.execute
|
||||
|
||||
const executor = {
|
||||
async windows (exec) {
|
||||
const loopbackPath = extraPath.getEnableLoopbackPath()
|
||||
|
@ -10,10 +12,10 @@ const executor = {
|
|||
await execFile(loopbackPath)
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
throw Error('不支持此操作')
|
||||
throw new Error('不支持此操作')
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
throw Error('不支持此操作')
|
||||
throw new Error('不支持此操作')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const log = require('../../../utils/util.log')
|
||||
const path = require('path')
|
||||
const log = require('../../../utils/util.log')
|
||||
|
||||
function getExtraPath () {
|
||||
let extraPath = process.env.DS_EXTRA_PATH
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
/**
|
||||
* 获取环境变量
|
||||
*/
|
||||
const Shell = require('../shell')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const Shell = require('../shell')
|
||||
|
||||
const execute = Shell.execute
|
||||
|
||||
const executor = {
|
||||
async windows (exec) {
|
||||
const ret = await exec(['npm config list --json'], { type: 'cmd' })
|
||||
|
@ -14,10 +16,10 @@ const executor = {
|
|||
return {}
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
throw new Error('暂未实现此功能')
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
throw new Error('暂未实现此功能')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
* 获取环境变量
|
||||
*/
|
||||
const Shell = require('../shell')
|
||||
|
||||
const execute = Shell.execute
|
||||
|
||||
const executor = {
|
||||
async windows (exec) {
|
||||
const ret = await exec(['set'], { type: 'cmd' })
|
||||
|
@ -19,10 +21,10 @@ const executor = {
|
|||
return map
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
throw new Error('暂未实现此功能')
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
throw new Error('暂未实现此功能')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const Shell = require('../shell')
|
||||
|
||||
const execute = Shell.execute
|
||||
|
||||
const executor = {
|
||||
|
@ -9,11 +10,11 @@ const executor = {
|
|||
return true
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
await exec('kill `lsof -i:' + port + " |grep 'dev-sidecar\\|electron\\|@docmirro' |awk '{print $2}'`")
|
||||
await exec(`kill \`lsof -i:${port} |grep 'dev-sidecar\\|electron\\|@docmirro' |awk '{print $2}'\``)
|
||||
return true
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
await exec('kill `lsof -i:' + port + " |grep 'dev-side\\|Elect' |awk '{print $2}'`")
|
||||
await exec(`kill \`lsof -i:${port} |grep 'dev-side\\|Elect' |awk '{print $2}'\``)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
* 设置环境变量
|
||||
*/
|
||||
const Shell = require('../shell')
|
||||
|
||||
const execute = Shell.execute
|
||||
|
||||
const executor = {
|
||||
async windows (exec, { list }) {
|
||||
const cmds = []
|
||||
|
@ -13,10 +15,10 @@ const executor = {
|
|||
return ret
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
throw new Error('暂未实现此功能')
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
throw new Error('暂未实现此功能')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
* 设置环境变量
|
||||
*/
|
||||
const Shell = require('../shell')
|
||||
|
||||
const execute = Shell.execute
|
||||
|
||||
const executor = {
|
||||
async windows (exec, { list }) {
|
||||
const cmds = []
|
||||
|
@ -22,10 +24,10 @@ const executor = {
|
|||
return ret
|
||||
},
|
||||
async linux (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
throw new Error('暂未实现此功能')
|
||||
},
|
||||
async mac (exec, { port }) {
|
||||
throw Error('暂未实现此功能')
|
||||
throw new Error('暂未实现此功能')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
/**
|
||||
* 获取环境变量
|
||||
*/
|
||||
const Shell = require('../../shell')
|
||||
const Registry = require('winreg')
|
||||
|
||||
const execute = Shell.execute
|
||||
const execFile = Shell.execFile
|
||||
const log = require('../../../utils/util.log')
|
||||
const extraPath = require('../extra-path/index')
|
||||
const Shell = require('../../shell')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const request = require('request')
|
||||
const log = require('../../../utils/util.log')
|
||||
const extraPath = require('../extra-path/index')
|
||||
|
||||
const execute = Shell.execute
|
||||
const execFile = Shell.execFile
|
||||
|
||||
let config = null
|
||||
function loadConfig () {
|
||||
|
@ -20,7 +20,6 @@ function loadConfig () {
|
|||
}
|
||||
|
||||
async function _winUnsetProxy (exec, setEnv) {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
const proxyPath = extraPath.getProxyExePath()
|
||||
await execFile(proxyPath, ['set', '1'])
|
||||
|
||||
|
@ -74,12 +73,12 @@ async function downloadDomesticDomainAllowListAsync () {
|
|||
|
||||
let fileTxt = body
|
||||
try {
|
||||
if (fileTxt.indexOf('*.') < 0) {
|
||||
if (!fileTxt.includes('*.')) {
|
||||
fileTxt = Buffer.from(fileTxt, 'base64').toString('utf8')
|
||||
// log.debug('解析 base64 后的 domestic-domain-allowlist:', fileTxt)
|
||||
}
|
||||
} catch (e) {
|
||||
if (fileTxt.indexOf('*.') < 0) {
|
||||
if (!fileTxt.includes('*.')) {
|
||||
log.error(`远程 domestic-domain-allowlist.txt 文件内容即不是base64格式,也不是要求的格式,url: ${remoteFileUrl},body: ${body}`)
|
||||
return
|
||||
}
|
||||
|
@ -195,7 +194,7 @@ function getProxyExcludeIpStr (split) {
|
|||
try {
|
||||
let domesticDomainAllowList = getDomesticDomainAllowList()
|
||||
if (domesticDomainAllowList) {
|
||||
domesticDomainAllowList = (domesticDomainAllowList + '\n').replaceAll(/[\r\n]+/g, '\n').replaceAll(/[^\n]*[^*.a-zA-Z\d-\n]+[^\n]*\r?\n/g, '').trim().replaceAll(/\s*\n+\s*/g, split)
|
||||
domesticDomainAllowList = (`${domesticDomainAllowList}\n`).replaceAll(/[\r\n]+/g, '\n').replaceAll(/[\d*\-.A-Z]*[^\d\n*\-.A-Z][^\n]*\n/gi, '').trim().replaceAll(/\s*\n\s*/g, split)
|
||||
if (domesticDomainAllowList) {
|
||||
excludeIpStr += domesticDomainAllowList
|
||||
log.info('系统代理排除列表拼接国内域名')
|
||||
|
@ -224,7 +223,7 @@ async function _winSetProxy (exec, ip, port, setEnv) {
|
|||
let proxyAddr = `https=http://${ip}:${port}`
|
||||
// http
|
||||
if (config.get().proxy.proxyHttp) {
|
||||
proxyAddr = `http=http://${ip}:${port - 1};` + proxyAddr
|
||||
proxyAddr = `http=http://${ip}:${port - 1};${proxyAddr}`
|
||||
}
|
||||
|
||||
// 读取排除域名
|
||||
|
@ -283,12 +282,12 @@ const executor = {
|
|||
setProxyCmd.push(`gsettings set org.gnome.system.proxy.http host ${ip}`)
|
||||
setProxyCmd.push(`gsettings set org.gnome.system.proxy.http port ${port - 1}`)
|
||||
} else {
|
||||
setProxyCmd.push("gsettings set org.gnome.system.proxy.http host ''")
|
||||
setProxyCmd.push('gsettings set org.gnome.system.proxy.http host \'\'')
|
||||
setProxyCmd.push('gsettings set org.gnome.system.proxy.http port 0')
|
||||
}
|
||||
|
||||
// 设置排除域名(ignore-hosts)
|
||||
const excludeIpStr = getProxyExcludeIpStr("', '")
|
||||
const excludeIpStr = getProxyExcludeIpStr('\', \'')
|
||||
setProxyCmd.push(`gsettings set org.gnome.system.proxy ignore-hosts "['${excludeIpStr}']"`)
|
||||
|
||||
await exec(setProxyCmd)
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
const Shell = require('../shell')
|
||||
|
||||
const execute = Shell.execute
|
||||
|
||||
const executor = {
|
||||
async windows (exec, { certPath }) {
|
||||
const cmds = ['start "" "' + certPath + '"']
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const ret = await exec(cmds, { type: 'cmd' })
|
||||
const cmds = [`start "" "${certPath}"`]
|
||||
await exec(cmds, { type: 'cmd' })
|
||||
return true
|
||||
},
|
||||
async linux (exec, { certPath }) {
|
||||
const cmds = [`sudo cp ${certPath} /usr/local/share/ca-certificates`, 'sudo update-ca-certificates ']
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const ret = await exec(cmds)
|
||||
await exec(cmds)
|
||||
return true
|
||||
},
|
||||
async mac (exec, { certPath }) {
|
||||
const cmds = ['open "' + certPath + '"']
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const ret = await exec(cmds, { type: 'cmd' })
|
||||
const cmds = [`open "${certPath}"`]
|
||||
await exec(cmds, { type: 'cmd' })
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
const os = require('os')
|
||||
const childProcess = require('child_process')
|
||||
const _execFile = childProcess.execFile
|
||||
const PowerShell = require('node-powershell')
|
||||
const log = require('../utils/util.log')
|
||||
const os = require('os')
|
||||
const fixPath = require('fix-path')
|
||||
const iconv = require('iconv-lite')
|
||||
const PowerShell = require('node-powershell')
|
||||
const log = require('../utils/util.log')
|
||||
|
||||
const _execFile = childProcess.execFile
|
||||
|
||||
fixPath()
|
||||
|
||||
class SystemShell {
|
||||
static async exec (cmds, args) {
|
||||
throw new Error('You have to implement the method exec!')
|
||||
|
@ -63,7 +66,7 @@ class WindowsSystemShell extends SystemShell {
|
|||
} else {
|
||||
let compose = 'echo "test" ' // 'chcp 65001 '
|
||||
for (const cmd of cmds) {
|
||||
compose += ' && ' + cmd
|
||||
compose += ` && ${cmd}`
|
||||
}
|
||||
// compose += '&& exit'
|
||||
const ret = await childExec(compose, args)
|
||||
|
@ -77,7 +80,7 @@ function _childExec (composeCmds, options = {}) {
|
|||
return new Promise((resolve, reject) => {
|
||||
const childProcess = require('child_process')
|
||||
log.info('shell:', composeCmds)
|
||||
childProcess.exec(composeCmds, options, function (error, stdout, stderr) {
|
||||
childProcess.exec(composeCmds, options, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
if (options.printErrorLog !== false) {
|
||||
log.error('cmd 命令执行错误:\n===>\ncommands:', composeCmds, '\n error:', error, '\n<===')
|
||||
|
@ -100,7 +103,7 @@ function childExec (composeCmds, options = {}) {
|
|||
|
||||
const childProcess = require('child_process')
|
||||
log.info('shell:', composeCmds)
|
||||
childProcess.exec(composeCmds, { encoding: binaryEncoding }, function (error, stdout, stderr) {
|
||||
childProcess.exec(composeCmds, { encoding: binaryEncoding }, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
// console.log('------', decoder.decode(stderr))
|
||||
const message = iconv.decode(Buffer.from(stderr, binaryEncoding), encoding)
|
||||
|
|
|
@ -34,8 +34,9 @@
|
|||
// console.error(e)
|
||||
// })
|
||||
|
||||
const request = require('request')
|
||||
const fs = require('fs')
|
||||
const request = require('request')
|
||||
|
||||
request({
|
||||
url: 'https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js',
|
||||
proxy: 'http://127.0.0.1:31181',
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const event = require('./event')
|
||||
const lodash = require('lodash')
|
||||
const event = require('./event')
|
||||
const log = require('./utils/util.log')
|
||||
|
||||
const status = {
|
||||
server: { enabled: false },
|
||||
proxy: {},
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
const path = require('path')
|
||||
const log4js = require('log4js')
|
||||
const config = require('../config/index')
|
||||
|
||||
const level = process.env.NODE_ENV === 'development' ? 'debug' : 'info'
|
||||
|
||||
function getDefaultConfigBasePath () {
|
||||
return config.server.setting.userBasePath
|
||||
}
|
||||
const level = process.env.NODE_ENV === 'development' ? 'debug' : 'info'
|
||||
const path = require('path')
|
||||
|
||||
const filename = path.join(getDefaultConfigBasePath(), '/logs/core.log')
|
||||
log4js.configure({
|
||||
appenders: { std: { type: 'stdout' }, file: { type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename } },
|
||||
categories: { default: { appenders: ['file', 'std'], level: level } }
|
||||
categories: { default: { appenders: ['file', 'std'], level } }
|
||||
})
|
||||
const logger = log4js.getLogger('core')
|
||||
module.exports = logger
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const fs = require('fs')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const DevSidecar = require('../index')
|
||||
const fs = require('fs')
|
||||
const log = require('../src/utils/util.log')
|
||||
|
||||
// 启动服务
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const server = require('@docmirror/mitmproxy')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const path = require('path')
|
||||
const home = process.env.USER_HOME || process.env.HOME || 'C:/Users/Administrator/'
|
||||
const log = require('../src/utils/util.log')
|
||||
|
||||
const home = process.env.USER_HOME || process.env.HOME || 'C:/Users/Administrator/'
|
||||
|
||||
let configPath
|
||||
if (process.argv && process.argv.length > 3) {
|
||||
configPath = process.argv[2]
|
||||
|
@ -11,7 +13,6 @@ if (process.argv && process.argv.length > 3) {
|
|||
configPath = path.join(home, '.dev-sidecar/running.json')
|
||||
}
|
||||
|
||||
const fs = require('fs')
|
||||
const configJson = fs.readFileSync(configPath)
|
||||
log.info('读取 running.json by core 成功:', configPath)
|
||||
const config = jsonApi.parse(configJson.toString())
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
{
|
||||
app: {
|
||||
autoStart: {
|
||||
enabled: true,
|
||||
"app": {
|
||||
"autoStart": {
|
||||
"enabled": true
|
||||
},
|
||||
mode: 'default',
|
||||
},
|
||||
plugin: {
|
||||
node: {
|
||||
setting: {
|
||||
yarnRegistry: 'null',
|
||||
},
|
||||
},
|
||||
git: {
|
||||
enabled: true,
|
||||
},
|
||||
overwall: {
|
||||
enabled: false,
|
||||
targets: {
|
||||
'*gagedigital.com': true,
|
||||
'*yonsz.net': true,
|
||||
'*bootstrapcdn.com': true,
|
||||
'*cloudflare.com': true,
|
||||
'help.yonsz.net': true,
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
intercepts: {
|
||||
'dev-sidecar.docmirror.cn': {
|
||||
'.*': {
|
||||
proxy: 'dev-sidecar-preview.docmirror.cn',
|
||||
},
|
||||
},
|
||||
'test1111.gagedigital.com': {
|
||||
'.*': {
|
||||
proxy: 'test1.gagedigital.com',
|
||||
"mode": "default"
|
||||
},
|
||||
"plugin": {
|
||||
"node": {
|
||||
"setting": {
|
||||
"yarnRegistry": "null"
|
||||
}
|
||||
},
|
||||
"git": {
|
||||
"enabled": true
|
||||
},
|
||||
"overwall": {
|
||||
"enabled": false,
|
||||
"targets": {
|
||||
"*gagedigital.com": true,
|
||||
"*yonsz.net": true,
|
||||
"*bootstrapcdn.com": true,
|
||||
"*cloudflare.com": true,
|
||||
"help.yonsz.net": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"server": {
|
||||
"intercepts": {
|
||||
"dev-sidecar.docmirror.cn": {
|
||||
".*": {
|
||||
"proxy": "dev-sidecar-preview.docmirror.cn"
|
||||
}
|
||||
},
|
||||
"test1111.gagedigital.com": {
|
||||
".*": {
|
||||
"proxy": "test1.gagedigital.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
const https = require('https')
|
||||
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1'
|
||||
|
||||
function request () {
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
|
@ -28,12 +30,12 @@ function request () {
|
|||
})
|
||||
}
|
||||
// eslint-disable-next-line no-undef
|
||||
describe('ssl.verify', function () {
|
||||
describe('ssl.verify', () => {
|
||||
// eslint-disable-next-line no-undef
|
||||
it('regex.test.js', async function () {
|
||||
it('regex.test.js', async () => {
|
||||
// https.request('https://test1.gagedigital.com/ssltest.php')
|
||||
await request()
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
|
||||
// expect(ret).be.ok
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const expect = require('chai').expect
|
||||
// eslint-disable-next-line no-undef
|
||||
describe('test', function () {
|
||||
describe('test', () => {
|
||||
// eslint-disable-next-line no-undef
|
||||
it('regexp', function () {
|
||||
it('regexp', () => {
|
||||
const test = '^/[^/]+/[^/]+(/releases(/.*)?)?$'
|
||||
const reg = new RegExp(test)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const request = require('request')
|
||||
const HttpsAgent = require('@docmirror/mitmproxy/src/lib/proxy/common/ProxyHttpsAgent')
|
||||
const request = require('request')
|
||||
|
||||
const options = {
|
||||
url: 'https://raw.githubusercontent.com/docmirror/dev-sidecar/refs/heads/master/packages/core/src/config/remote_config.json5',
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"@docmirror/dev-sidecar": "^1.8.9",
|
||||
"@docmirror/mitmproxy": "^1.8.9",
|
||||
"@mihomo-party/sysproxy": "^2.0.4",
|
||||
"@natmri/platform-napi": "^0.0.8",
|
||||
"@natmri/platform-napi": "^0.0.7",
|
||||
"adm-zip": "^0.5.5",
|
||||
"ant-design-vue": "^1.6.5",
|
||||
"compressing": "^1.5.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const pkg = require('../package.json')
|
||||
const fs = require('fs')
|
||||
|
||||
function appendIntro (context, systemType, latest) {
|
||||
const version = pkg.version
|
||||
|
@ -14,8 +14,7 @@ partMiniVersion: 1.7.0
|
|||
releaseNotes:
|
||||
- 升级日志
|
||||
- https://download.fastgit.org/docmirror/dev-sidecar/releases/download/v${version}/DevSidecar-${version}.exe
|
||||
`,
|
||||
(err) => {
|
||||
`, (err) => {
|
||||
if (err) {
|
||||
console.log('修改latest 失败')
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const AdmZip = require('adm-zip')
|
||||
const pkg = require('../package.json')
|
||||
const fs = require('fs')
|
||||
|
||||
function writeAppUpdateYmlForLinux () {
|
||||
const publishUrl = process.env.VUE_APP_PUBLISH_URL
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
'use strict'
|
||||
/* global __static */
|
||||
import path from 'path'
|
||||
import { app, protocol, BrowserWindow, Menu, Tray, ipcMain, dialog, powerMonitor, nativeImage, nativeTheme, globalShortcut } from 'electron'
|
||||
import DevSidecar from '@docmirror/dev-sidecar'
|
||||
import { app, BrowserWindow, dialog, globalShortcut, ipcMain, Menu, nativeImage, nativeTheme, powerMonitor, protocol, Tray } from 'electron'
|
||||
import minimist from 'minimist'
|
||||
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
|
||||
import backend from './bridge/backend'
|
||||
import DevSidecar from '@docmirror/dev-sidecar'
|
||||
import log from './utils/util.log'
|
||||
import minimist from 'minimist'
|
||||
|
||||
const isWindows = process.platform === 'win32'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const isMac = process.platform === 'darwin'
|
||||
// import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
|
||||
// 避免其他系统出现异常,只有 Windows 使用 './background/powerMonitor'
|
||||
|
@ -21,7 +19,7 @@ const _powerMonitor = isWindows ? require('./background/powerMonitor').powerMoni
|
|||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let win
|
||||
let winIsHidden = false
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
let tray // 防止被内存清理
|
||||
let forceClose = false
|
||||
DevSidecar.api.config.reload()
|
||||
|
@ -123,8 +121,8 @@ function setTray () {
|
|||
showWin()
|
||||
})
|
||||
|
||||
appTray.on('right-click', function () {
|
||||
setTimeout(function () {
|
||||
appTray.on('right-click', () => {
|
||||
setTimeout(() => {
|
||||
appTray.popUpContextMenu(contextMenu)
|
||||
}, 200)
|
||||
})
|
||||
|
@ -184,7 +182,6 @@ function createWindow (startHideWindow) {
|
|||
nodeIntegration: true// process.env.ELECTRON_NODE_INTEGRATION
|
||||
},
|
||||
show: !startHideWindow,
|
||||
// eslint-disable-next-line no-undef
|
||||
icon: path.join(__static, 'icon.png')
|
||||
})
|
||||
winIsHidden = !!startHideWindow
|
||||
|
@ -368,7 +365,7 @@ if (app.getLoginItemSettings().wasOpenedAsHidden) {
|
|||
log.info('start args:', args)
|
||||
|
||||
// 通过启动参数,判断是否隐藏窗口
|
||||
const hideWindowArg = args.hideWindow + ''
|
||||
const hideWindowArg = `${args.hideWindow}`
|
||||
if (hideWindowArg === 'true' || hideWindowArg === '1') {
|
||||
startHideWindow = true
|
||||
} else if (hideWindowArg === 'false' || hideWindowArg === '0') {
|
||||
|
@ -483,7 +480,7 @@ if (isDevelopment) {
|
|||
}
|
||||
}
|
||||
// 系统关机和重启时的操作
|
||||
process.on('exit', function () {
|
||||
process.on('exit', () => {
|
||||
log.info('进程结束,退出app')
|
||||
quit()
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { acquireShutdownBlock, insertWndProcHook, releaseShutdownBlock, removeWndProcHook, setMainWindowHandle } from '@natmri/platform-napi'
|
||||
import { powerMonitor as _powerMonitor } from 'electron'
|
||||
import { setMainWindowHandle, insertWndProcHook, removeWndProcHook, releaseShutdownBlock, acquireShutdownBlock } from '@natmri/platform-napi'
|
||||
|
||||
class PowerMonitor {
|
||||
constructor () {
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import lodash from 'lodash'
|
||||
import DevSidecar from '@docmirror/dev-sidecar'
|
||||
import { ipcMain } from 'electron'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import DevSidecar from '@docmirror/dev-sidecar'
|
||||
import { ipcMain } from 'electron'
|
||||
import lodash from 'lodash'
|
||||
|
||||
const pk = require('../../../package.json')
|
||||
const mitmproxyPath = path.join(__dirname, 'mitmproxy.js')
|
||||
process.env.DS_EXTRA_PATH = path.join(__dirname, '../extra/')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const log = require('../../utils/util.log')
|
||||
|
||||
const mitmproxyPath = path.join(__dirname, 'mitmproxy.js')
|
||||
process.env.DS_EXTRA_PATH = path.join(__dirname, '../extra/')
|
||||
|
||||
const getDefaultConfigBasePath = function () {
|
||||
return DevSidecar.api.config.get().server.setting.userBasePath
|
||||
}
|
||||
|
@ -129,7 +131,7 @@ function _deepFindFunction (list, parent, parentKey) {
|
|||
if (item instanceof Function) {
|
||||
list.push(parentKey + key)
|
||||
} else if (item instanceof Object) {
|
||||
_deepFindFunction(list, item, parentKey + key + '.')
|
||||
_deepFindFunction(list, item, `${parentKey + key}.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,14 +186,20 @@ export default {
|
|||
// 注册从core里来的事件,并转发给view
|
||||
DevSidecar.api.event.register('status', (event) => {
|
||||
log.info('bridge on status, event:', event)
|
||||
if (win) win.webContents.send('status', { ...event })
|
||||
if (win) {
|
||||
win.webContents.send('status', { ...event })
|
||||
}
|
||||
})
|
||||
DevSidecar.api.event.register('error', (event) => {
|
||||
log.error('bridge on error, event:', event)
|
||||
if (win) win.webContents.send('error.core', event)
|
||||
if (win) {
|
||||
win.webContents.send('error.core', event)
|
||||
}
|
||||
})
|
||||
DevSidecar.api.event.register('speed', (event) => {
|
||||
if (win) win.webContents.send('speed', event)
|
||||
if (win) {
|
||||
win.webContents.send('speed', event)
|
||||
}
|
||||
})
|
||||
|
||||
// 合并用户配置
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import Sudoer from 'electron-sudo'
|
||||
import DevSidecar from '@docmirror/dev-sidecar'
|
||||
import Sudoer from 'electron-sudo'
|
||||
|
||||
export default {
|
||||
async open () {
|
||||
const options = { name: '设置loopback' }
|
||||
const sudoer = new Sudoer(options)
|
||||
const exeFile = DevSidecar.api.shell.extraPath.getEnableLoopbackPath()
|
||||
await sudoer.exec(
|
||||
exeFile, { env: { PARAM: 'VALUE' } }
|
||||
exeFile,
|
||||
{ env: { PARAM: 'VALUE' } }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,8 @@ export default {
|
|||
openAtLogin: true,
|
||||
openAsHidden: true,
|
||||
args: [
|
||||
'--hideWindow', '"true"'
|
||||
'--hideWindow',
|
||||
'"true"'
|
||||
]
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
function install (app, api) {
|
||||
api.ipc.on('auto-start', (event, message) => {
|
||||
if (message.value === true) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import api from './api/backend'
|
||||
import autoStart from './auto-start/backend'
|
||||
import fileSelector from './file-selector/backend'
|
||||
import tongji from './tongji/backend'
|
||||
import update from './update/backend'
|
||||
import fileSelector from './file-selector/backend'
|
||||
import autoStart from './auto-start/backend'
|
||||
|
||||
const modules = {
|
||||
api, // 核心接口模块
|
||||
|
|
|
@ -13,15 +13,14 @@ function install (app, api) {
|
|||
|
||||
function handleServerStartError (message, err, app, api) {
|
||||
if (message.value === 'EADDRINUSE') {
|
||||
// eslint-disable-next-line no-debugger
|
||||
app.$confirm({
|
||||
title: '端口被占用,代理服务启动失败',
|
||||
content: '是否要杀掉占用进程?您也可以点击取消,然后前往加速服务->基本设置中修改代理端口',
|
||||
onOk () {
|
||||
// TODO 杀掉进程
|
||||
api.config.get().then(config => {
|
||||
api.config.get().then((config) => {
|
||||
console.log('config', config)
|
||||
api.shell.killByPort({ port: config.server.port }).then(ret => {
|
||||
api.shell.killByPort({ port: config.server.port }).then((ret) => {
|
||||
app.$message.info('杀掉进程成功,请重试开启代理服务')
|
||||
})
|
||||
})
|
||||
|
@ -31,7 +30,7 @@ function handleServerStartError (message, err, app, api) {
|
|||
}
|
||||
})
|
||||
} else {
|
||||
app.$message.error('加速服务启动失败:' + message.message)
|
||||
app.$message.error(`加速服务启动失败:${message.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
export default {
|
||||
install (context) {
|
||||
const { ipcMain, dialog, log } = context
|
||||
ipcMain.on('file-selector', function (event, message) {
|
||||
ipcMain.on('file-selector', (event, message) => {
|
||||
if (message.key === 'open') {
|
||||
dialog.showOpenDialog({
|
||||
properties: ['openFile'],
|
||||
...message
|
||||
}).then(result => {
|
||||
}).then((result) => {
|
||||
if (result.canceled) {
|
||||
event.sender.send('file-selector', { key: 'canceled' })
|
||||
} else {
|
||||
event.sender.send('file-selector', { key: 'selected', value: result.filePaths })
|
||||
}
|
||||
}).catch(err => {
|
||||
}).catch((err) => {
|
||||
log.error('选择文件失败:', err)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
|
||||
function install (app, api) {
|
||||
api.fileSelector = {
|
||||
open (value, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
api.ipc.send('file-selector', { key: 'open', value: value, ...options })
|
||||
api.ipc.send('file-selector', { key: 'open', value, ...options })
|
||||
api.ipc.on('file-selector', (event, message) => {
|
||||
console.log('selector', message)
|
||||
if (message.key === 'selected') {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// import api from './api/front'
|
||||
import autoStart from './auto-start/front'
|
||||
import error from './error/front'
|
||||
import fileSelector from './file-selector/front'
|
||||
import onClose from './on-close/front'
|
||||
import tongji from './tongji/front'
|
||||
import update from './update/front'
|
||||
import fileSelector from './file-selector/front'
|
||||
import autoStart from './auto-start/front'
|
||||
import onClose from './on-close/front'
|
||||
|
||||
const modules = {
|
||||
// api, // 核心接口模块
|
||||
error,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// eslint-disable-next-line no-unused-vars
|
||||
const log = require('../utils/util.log')
|
||||
const server = require('@docmirror/mitmproxy')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const configPath = process.argv[2]
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const server = require('@docmirror/mitmproxy')
|
||||
const jsonApi = require('@docmirror/mitmproxy/src/json')
|
||||
const log = require('../utils/util.log')
|
||||
|
||||
const configPath = process.argv[2]
|
||||
const configJson = fs.readFileSync(configPath)
|
||||
log.info('读取 running.json by gui bridge 成功:', configPath)
|
||||
const config = jsonApi.parse(configJson.toString())
|
||||
|
|
|
@ -12,19 +12,21 @@ function install (app, api) {
|
|||
}
|
||||
app.$confirm({
|
||||
title: '关闭策略',
|
||||
content: h => <div>
|
||||
<div style={'margin-top:10px'}>
|
||||
content: (h) => (
|
||||
<div>
|
||||
<div style="margin-top:10px">
|
||||
<a-radio-group vOn:change={onRadioChange} defaultValue={closeType}>
|
||||
<a-radio value={1}>直接关闭</a-radio>
|
||||
<a-radio value={2}>最小化到系统托盘</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
<div style={'margin-top:10px'}>
|
||||
<div style="margin-top:10px">
|
||||
<a-checkbox vOn:change={onCheckChange} defaultChecked={doSave}>
|
||||
记住本次选择,不再提示
|
||||
< /a-checkbox>
|
||||
</a-checkbox>
|
||||
</div>
|
||||
</div>,
|
||||
</div>
|
||||
),
|
||||
async onOk () {
|
||||
console.log('OK. closeType=', closeType)
|
||||
if (doSave) {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
|
||||
/**
|
||||
* first step
|
||||
* @param {*} ipcMain
|
||||
*/
|
||||
const ebtMain = (ipcMain) => {
|
||||
function ebtMain (ipcMain) {
|
||||
const isDevelopment = process.env.NODE_ENV !== 'production'
|
||||
const request = require('request')
|
||||
/* istanbul ignore else */
|
||||
|
@ -21,15 +20,14 @@ const ebtMain = (ipcMain) => {
|
|||
headers: {
|
||||
Referer: 'https://hm.baidu.com/'
|
||||
}
|
||||
},
|
||||
(err, response, body) => {
|
||||
}, (err, response, body) => {
|
||||
if (err) {
|
||||
console.error('百度统计请求出错', err)
|
||||
return
|
||||
}
|
||||
const rource = '(h.c.b.su=h.c.b.u||document.location.href),h.c.b.u=f.protocol+"//"+document.location.host+'
|
||||
/* istanbul ignore else */
|
||||
if (body && body.indexOf(rource) >= 0) {
|
||||
if (body && body.includes(rource)) {
|
||||
// step 3
|
||||
let text = body
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
|
||||
/**
|
||||
* second step
|
||||
* @param {*} ipcRenderer
|
||||
* @param {*} siteId
|
||||
* @param {*} router
|
||||
*/
|
||||
const ebtRenderer = (ipcRenderer, siteId, router) => {
|
||||
function ebtRenderer (ipcRenderer, siteId, router) {
|
||||
/* istanbul ignore else */
|
||||
if (!(ipcRenderer && ipcRenderer.on && ipcRenderer.send)) {
|
||||
throw new TypeError('require ipcRenderer')
|
||||
|
@ -38,7 +37,7 @@ const ebtRenderer = (ipcRenderer, siteId, router) => {
|
|||
router.beforeEach((to, _, next) => {
|
||||
/* istanbul ignore else */
|
||||
if (to.path) {
|
||||
window._hmt.push(['_trackPageview', '/#' + to.fullPath])
|
||||
window._hmt.push(['_trackPageview', `/#${to.fullPath}`])
|
||||
console.log('baidu trace', to.fullPath)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import DevSidecar from '@docmirror/dev-sidecar'
|
||||
import AdmZip from 'adm-zip'
|
||||
import { ipcMain } from 'electron'
|
||||
import { autoUpdater } from 'electron-updater'
|
||||
import path from 'path'
|
||||
import request from 'request'
|
||||
import progress from 'request-progress'
|
||||
import fs from 'fs'
|
||||
import AdmZip from 'adm-zip'
|
||||
import log from '../../utils/util.log'
|
||||
import appPathUtil from '../../utils/util.apppath'
|
||||
import pkg from '../../../package.json'
|
||||
import DevSidecar from '@docmirror/dev-sidecar'
|
||||
import appPathUtil from '../../utils/util.apppath'
|
||||
import log from '../../utils/util.log'
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const isMac = process.platform === 'darwin'
|
||||
const isLinux = process.platform === 'linux'
|
||||
|
||||
|
@ -24,16 +23,16 @@ function downloadFile (uri, filePath, onProgress, onSuccess, onError) {
|
|||
// delay: 1000, // Only start to emit after 1000ms delay, defaults to 0ms
|
||||
// lengthHeader: 'x-transfer-length' // Length header to use, defaults to content-length
|
||||
})
|
||||
.on('progress', function (state) {
|
||||
.on('progress', (state) => {
|
||||
onProgress(state.percent * 100)
|
||||
log.log('progress', state.percent)
|
||||
})
|
||||
.on('error', function (err) {
|
||||
.on('error', (err) => {
|
||||
// Do something with err
|
||||
log.error('下载升级包失败:', err)
|
||||
onError(err)
|
||||
})
|
||||
.on('end', function () {
|
||||
.on('end', () => {
|
||||
// Do something after request finishes
|
||||
onSuccess()
|
||||
})
|
||||
|
@ -44,9 +43,9 @@ function parseVersion (version) {
|
|||
const matched = version.match(/^v?(\d+\.\d+\.\d+)(.*)$/)
|
||||
const versionArr = matched[1].split('.')
|
||||
return {
|
||||
major: parseInt(versionArr[0]),
|
||||
minor: parseInt(versionArr[1]),
|
||||
patch: parseInt(versionArr[2]),
|
||||
major: Number.parseInt(versionArr[0]),
|
||||
minor: Number.parseInt(versionArr[1]),
|
||||
patch: Number.parseInt(versionArr[2]),
|
||||
suffix: matched[2]
|
||||
}
|
||||
}
|
||||
|
@ -141,11 +140,11 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
// 检查更新
|
||||
const releasesApiUrl = 'https://api.github.com/repos/docmirror/dev-sidecar/releases'
|
||||
async function checkForUpdatesFromGitHub () {
|
||||
request(releasesApiUrl, { headers: { 'User-Agent': 'DS/' + curVersion, 'Server-Name': 'baidu.com' } }, (error, response, body) => {
|
||||
request(releasesApiUrl, { headers: { 'User-Agent': `DS/${curVersion}`, 'Server-Name': 'baidu.com' } }, (error, response, body) => {
|
||||
try {
|
||||
if (error) {
|
||||
log.error('检查更新失败:', error)
|
||||
const errorMsg = '检查更新失败:' + error
|
||||
const errorMsg = `检查更新失败:${error}`
|
||||
win.webContents.send('update', { key: 'error', action: 'checkForUpdate', error: errorMsg })
|
||||
return
|
||||
}
|
||||
|
@ -203,7 +202,7 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
value: {
|
||||
version,
|
||||
releaseNotes: versionData.body
|
||||
? (versionData.body.replace(/\r\n/g, '\n').replace(/https:\/\/github.com\/docmirror\/dev-sidecar/g, '').replace(/(?<=(^|\n))[ \t]*[ #]*#\s*/g, '') || '无')
|
||||
? (versionData.body.replace(/\r\n/g, '\n').replace(/https:\/\/github.com\/docmirror\/dev-sidecar/g, '').replace(/(?<=(^|\n))[ \t]*(?:#[ #]*)?#\s*/g, '') || '无')
|
||||
: '无'
|
||||
}
|
||||
})
|
||||
|
@ -229,15 +228,15 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
|
||||
let message
|
||||
if (response) {
|
||||
message = '检查更新失败: ' + (bodyObj && bodyObj.message ? bodyObj.message : response.message) + ', code: ' + response.statusCode
|
||||
message = `检查更新失败: ${bodyObj && bodyObj.message ? bodyObj.message : response.message}, code: ${response.statusCode}`
|
||||
} else {
|
||||
message = '检查更新失败: ' + (bodyObj && bodyObj.message ? bodyObj.message : body)
|
||||
message = `检查更新失败: ${bodyObj && bodyObj.message ? bodyObj.message : body}`
|
||||
}
|
||||
win.webContents.send('update', { key: 'error', action: 'checkForUpdate', error: message })
|
||||
}
|
||||
} catch (e) {
|
||||
log.error('检查更新失败:', e)
|
||||
win.webContents.send('update', { key: 'error', action: 'checkForUpdate', error: '检查更新失败:' + e.message })
|
||||
win.webContents.send('update', { key: 'error', action: 'checkForUpdate', error: `检查更新失败:${e.message}` })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -252,10 +251,10 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
} catch (e) {
|
||||
fs.mkdirSync(fileDir)
|
||||
}
|
||||
const filePath = path.join(fileDir, value.version + '.zip')
|
||||
const filePath = path.join(fileDir, `${value.version}.zip`)
|
||||
|
||||
downloadFile(value.partPackage, filePath, (data) => {
|
||||
win.webContents.send('update', { key: 'progress', value: parseInt(data) })
|
||||
win.webContents.send('update', { key: 'progress', value: Number.parseInt(data) })
|
||||
}, () => {
|
||||
// 文件下载完成
|
||||
win.webContents.send('update', { key: 'progress', value: 100 })
|
||||
|
@ -263,10 +262,10 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
partPackagePath = filePath
|
||||
win.webContents.send('update', {
|
||||
key: 'downloaded',
|
||||
value: value
|
||||
value
|
||||
})
|
||||
}, (error) => {
|
||||
sendUpdateMessage({ key: 'error', value: error, error: error })
|
||||
sendUpdateMessage({ key: 'error', value: error, error })
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -294,30 +293,30 @@ function updateHandle (app, api, win, beforeQuit, quit, log) {
|
|||
}
|
||||
}
|
||||
|
||||
autoUpdater.on('error', function (error) {
|
||||
autoUpdater.on('error', (error) => {
|
||||
log.warn('autoUpdater error:', error)
|
||||
sendUpdateMessage({ key: 'error', value: error, error: error })
|
||||
sendUpdateMessage({ key: 'error', value: error, error })
|
||||
// dialog.showErrorBox('Error: ', error == null ? 'unknown' : (error.stack || error).toString())
|
||||
})
|
||||
autoUpdater.on('checking-for-update', function () {
|
||||
autoUpdater.on('checking-for-update', () => {
|
||||
log.info('autoUpdater checking-for-update')
|
||||
sendUpdateMessage({ key: 'checking', value: message.checking })
|
||||
})
|
||||
autoUpdater.on('update-available', function (info) {
|
||||
autoUpdater.on('update-available', (info) => {
|
||||
log.info('autoUpdater update-available')
|
||||
sendUpdateMessage({ key: 'available', value: info })
|
||||
})
|
||||
autoUpdater.on('update-not-available', function () {
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
log.info('autoUpdater update-not-available')
|
||||
sendUpdateMessage({ key: 'notAvailable', value: message.updateNotAva })
|
||||
})
|
||||
// 更新下载进度
|
||||
autoUpdater.on('download-progress', function (progressObj) {
|
||||
autoUpdater.on('download-progress', (progressObj) => {
|
||||
log.info('autoUpdater download-progress')
|
||||
win.webContents.send('update', { key: 'progress', value: parseInt(progressObj.percent) })
|
||||
win.webContents.send('update', { key: 'progress', value: Number.parseInt(progressObj.percent) })
|
||||
})
|
||||
// 更新完成,重启应用
|
||||
autoUpdater.on('update-downloaded', function (info) {
|
||||
autoUpdater.on('update-downloaded', (info) => {
|
||||
log.info('download complete, version:', info.version)
|
||||
win.webContents.send('update', {
|
||||
key: 'downloaded',
|
||||
|
|
|
@ -80,11 +80,13 @@ function install (app, api) {
|
|||
cancelText: '取消',
|
||||
okText: '打开链接',
|
||||
width: 420,
|
||||
content: h => {
|
||||
return <div>
|
||||
content: (h) => {
|
||||
return (
|
||||
<div>
|
||||
<div>请前往 <a onClick={openGithubUrl}>github项目release页面</a> 下载新版本手动安装</div>
|
||||
<div><a onClick={openGithubUrl}>https://github.com/docmirror/dev-sidecar/releases</a></div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
onOk () {
|
||||
openGithubUrl()
|
||||
|
@ -141,31 +143,35 @@ function install (app, api) {
|
|||
}
|
||||
console.log(value)
|
||||
app.$confirm({
|
||||
title: '发现新版本:v' + value.version,
|
||||
title: `发现新版本:v${value.version}`,
|
||||
cancelText: '暂不升级',
|
||||
okText: '升级',
|
||||
width: 700,
|
||||
content: h => {
|
||||
content: (h) => {
|
||||
if (value.releaseNotes) {
|
||||
const notes = []
|
||||
if (typeof value.releaseNotes === 'string') {
|
||||
const releaseNotes = value.releaseNotes.replace(/\r\n/g, '\n')
|
||||
return <div>
|
||||
return (
|
||||
<div>
|
||||
<div>发布公告:<a onClick={openGithubUrl}>https://github.com/docmirror/dev-sidecar/releases</a></div>
|
||||
<hr/>
|
||||
<pre style="max-height:350px;font-family:auto">
|
||||
{releaseNotes}
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
for (const note of value.releaseNotes) {
|
||||
notes.push(<li>{note}</li>)
|
||||
}
|
||||
return <div>
|
||||
return (
|
||||
<div>
|
||||
<div>发布公告:<a onClick={openGithubUrl}>https://github.com/docmirror/dev-sidecar/releases</a></div>
|
||||
<div>更新内容:</div>
|
||||
<ol>{notes}</ol>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -187,27 +193,31 @@ function install (app, api) {
|
|||
cancelText: '暂不升级',
|
||||
okText: '立即升级',
|
||||
width: 700,
|
||||
content: h => {
|
||||
content: (h) => {
|
||||
if (value.releaseNotes) {
|
||||
const notes = []
|
||||
if (typeof value.releaseNotes === 'string') {
|
||||
const releaseNotes = value.releaseNotes.replace(/\r\n/g, '\n')
|
||||
return <div>
|
||||
return (
|
||||
<div>
|
||||
<div>发布公告:<a onClick={openGithubUrl}>https://github.com/docmirror/dev-sidecar/releases</a></div>
|
||||
<hr/>
|
||||
<pre style="max-height:350px;font-family:auto">
|
||||
{releaseNotes}
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
for (const note of value.releaseNotes) {
|
||||
notes.push(<li>{note}</li>)
|
||||
}
|
||||
return <div>
|
||||
return (
|
||||
<div>
|
||||
<div>发布公告:<a onClick={openGithubUrl}>https://github.com/docmirror/dev-sidecar/releases</a></div>
|
||||
<div>更新内容:</div>
|
||||
<ol>{notes}</ol>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import Vue from 'vue'
|
||||
import App from './view/App.vue'
|
||||
import antd from 'ant-design-vue'
|
||||
import 'ant-design-vue/dist/antd.css'
|
||||
import view from './view'
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import routes from './view/router'
|
||||
import view from './view'
|
||||
import App from './view/App.vue'
|
||||
import DsContainer from './view/components/container'
|
||||
import routes from './view/router'
|
||||
import 'ant-design-vue/dist/antd.css'
|
||||
import './view/style/index.scss'
|
||||
import './view/style/theme/dark.scss' // 暗色主题
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import path from 'path'
|
||||
import os from 'os'
|
||||
import path from 'path'
|
||||
|
||||
function getSystemPlatform () {
|
||||
switch (os.platform()) {
|
||||
case 'darwin':
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
const log4js = require('log4js')
|
||||
const path = require('path')
|
||||
const DevSidecar = require('@docmirror/dev-sidecar')
|
||||
const log4js = require('log4js')
|
||||
|
||||
const level = process.env.NODE_ENV === 'development' ? 'debug' : 'info'
|
||||
|
||||
const getDefaultConfigBasePath = function () {
|
||||
return DevSidecar.api.config.get().server.setting.userBasePath
|
||||
}
|
||||
const level = process.env.NODE_ENV === 'development' ? 'debug' : 'info'
|
||||
const path = require('path')
|
||||
|
||||
const filename = path.join(getDefaultConfigBasePath(), '/logs/gui.log')
|
||||
log4js.configure({
|
||||
appenders: { std: { type: 'stdout' }, file: { type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename } },
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'ds-container'
|
||||
name: 'DsContainer'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="ds-container">
|
||||
<div class="body-wrapper">
|
||||
<div v-if="$slots.header" class="container-header"><slot name="header"></slot></div>
|
||||
<div class="container-body"> <slot></slot></div>
|
||||
<div class="container-footer"> <slot name="footer"></slot></div>
|
||||
<div v-if="$slots.header" class="container-header"><slot name="header" /></div>
|
||||
<div class="container-body"><slot /></div>
|
||||
<div class="container-footer"><slot name="footer" /></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -49,5 +49,4 @@ export default {
|
|||
padding:15px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'setup-ca',
|
||||
name: 'SetupCa',
|
||||
components: {
|
||||
|
||||
},
|
||||
|
@ -18,10 +18,6 @@ export default {
|
|||
systemPlatform: ''
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
const platform = await this.$api.info.getSystemPlatform()
|
||||
this.systemPlatform = platform
|
||||
},
|
||||
computed: {
|
||||
setupImage () {
|
||||
if (this.systemPlatform === 'mac') {
|
||||
|
@ -33,6 +29,10 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
const platform = await this.$api.info.getSystemPlatform()
|
||||
this.systemPlatform = platform
|
||||
},
|
||||
methods: {
|
||||
async openExternal (url) {
|
||||
await this.$api.ipc.openExternal(url)
|
||||
|
@ -61,27 +61,27 @@ export default {
|
|||
:closable="false"
|
||||
:visible="visible"
|
||||
:after-visible-change="afterVisibleChange"
|
||||
@close="onClose"
|
||||
width="660px"
|
||||
height="100%"
|
||||
:slots="{ title: 'title' }"
|
||||
wrapClassName="json-wrapper"
|
||||
wrap-class-name="json-wrapper"
|
||||
@close="onClose"
|
||||
>
|
||||
<template slot="title">
|
||||
{{title}}
|
||||
{{ title }}
|
||||
<a-button type="primary" style="float:right" @click="doSetup()">点此去安装</a-button>
|
||||
<a-button style="float:right;margin-right:10px;" @click="openExternal('https://github.com/docmirror/dev-sidecar/blob/master/doc/caroot.md')">为什么要安装证书?</a-button>
|
||||
</template>
|
||||
<div>
|
||||
<b>本应用在非“安全模式”下必须安装和信任CA根证书</b>,该证书是应用启动时本地随机生成的<br/>
|
||||
|
||||
<template v-if="this.systemPlatform === 'mac'">
|
||||
<template v-if="systemPlatform === 'mac'">
|
||||
1、点击右上角“点此去安装按钮”,打开钥匙串,<b style="color:red">选择”系统“</b><br/>
|
||||
2、然后按如下图步骤将随机生成的根证书设置为始终信任<br/>
|
||||
3、可能需要重新启动应用和浏览器才能生效<br/>
|
||||
4、注意:如果出现无法导入提示时,先点一下钥匙串的左边切换到<b style="color:red">“系统”栏</b>,然后再重新安装证书即可<br/>
|
||||
</template>
|
||||
<template v-else-if="this.systemPlatform === 'linux'">
|
||||
<template v-else-if="systemPlatform === 'linux'">
|
||||
1、点击右上角“点此去安装按钮”,将自动安装到系统证书库中<br/>
|
||||
2、<b color="red">火狐、chrome等浏览器不走系统证书</b>,需要手动安装(下图以chrome为例安装根证书)<br/>
|
||||
</template>
|
||||
|
@ -90,6 +90,6 @@ export default {
|
|||
2、然后按如下图步骤将根证书添加到<b style="color:red">信任的根证书颁发机构</b>
|
||||
</template>
|
||||
</div>
|
||||
<img width="100%" :src="setupImage"/>
|
||||
<img width="100%" :src="setupImage">
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import DsContainer from '../components/container'
|
||||
import lodash from 'lodash'
|
||||
import DsContainer from '../components/container'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
|
@ -1,21 +1,13 @@
|
|||
<script>
|
||||
import lodash from 'lodash'
|
||||
import setupCa from '../components/setup-ca'
|
||||
import DsContainer from '../components/container'
|
||||
import SetupCa from '../components/setup-ca'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
DsContainer,
|
||||
setupCa
|
||||
},
|
||||
computed: {
|
||||
_rootCaSetuped () {
|
||||
if (this.setting.rootCa) {
|
||||
return this.setting.rootCa.setuped === true
|
||||
}
|
||||
return false
|
||||
}
|
||||
SetupCa
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -52,6 +44,14 @@ export default {
|
|||
update: { checking: false, downloading: false, progress: 0, newVersion: false }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
_rootCaSetuped () {
|
||||
if (this.setting.rootCa) {
|
||||
return this.setting.rootCa.setuped === true
|
||||
}
|
||||
return false
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
await this.doCheckRootCa()
|
||||
await this.reloadConfig()
|
||||
|
@ -62,7 +62,7 @@ export default {
|
|||
this.update.autoChecked = true // 应用启动时,执行一次
|
||||
this.doCheckUpdate(false)
|
||||
}
|
||||
this.$api.info.get().then(ret => {
|
||||
this.$api.info.get().then((ret) => {
|
||||
this.info = ret
|
||||
})
|
||||
},
|
||||
|
@ -162,7 +162,7 @@ export default {
|
|||
this.$api.setting.save(this.setting)
|
||||
},
|
||||
reloadConfig () {
|
||||
return this.$api.config.reload().then(ret => {
|
||||
return this.$api.config.reload().then((ret) => {
|
||||
this.config = ret
|
||||
return ret
|
||||
})
|
||||
|
@ -257,26 +257,28 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ds-container class="page_index">
|
||||
<DsContainer class="page_index">
|
||||
<template slot="header">
|
||||
给开发者的辅助工具
|
||||
<span>
|
||||
<a-button style="margin-right:10px" @click="openSetupCa">
|
||||
<a-badge :count="_rootCaSetuped?0:1" dot>安装根证书</a-badge>
|
||||
<a-badge :count="_rootCaSetuped ? 0 : 1" dot>安装根证书</a-badge>
|
||||
</a-button>
|
||||
|
||||
<a-button style="margin-right:10px" @click="doCheckUpdate(true)" :loading="update.downloading || update.checking"
|
||||
:title="'当前版本:'+info.version">
|
||||
<a-badge :count="update.newVersion?1:0" dot>
|
||||
<span v-if="update.downloading">{{ update.progress }}%</span>{{ update.downloading ? '新版本下载中' : ('检查更新' + (update.checking ? '中' : '')) }}
|
||||
<a-button
|
||||
style="margin-right:10px" :loading="update.downloading || update.checking" :title="`当前版本:${info.version}`"
|
||||
@click="doCheckUpdate(true)"
|
||||
>
|
||||
<a-badge :count="update.newVersion ? 1 : 0" dot>
|
||||
<span v-if="update.downloading">{{ update.progress }}%</span>{{ update.downloading ? '新版本下载中' : (`检查更新${update.checking ? '中' : ''}`) }}
|
||||
</a-badge>
|
||||
</a-button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<div class="box">
|
||||
<a-alert v-if="config && config.app.showShutdownTip" message="本应用开启后会修改系统代理,直接重启电脑可能会无法上网,您可以再次启动本应用即可恢复。如您需要卸载,在卸载前请务必完全退出本应用再进行卸载" banner closable @close="onShutdownTipClose"/>
|
||||
<div class="mode-bar" style="margin:20px;" v-if="config && config.app">
|
||||
<a-alert v-if="config && config.app.showShutdownTip" message="本应用开启后会修改系统代理,直接重启电脑可能会无法上网,您可以再次启动本应用即可恢复。如您需要卸载,在卸载前请务必完全退出本应用再进行卸载" banner closable @close="onShutdownTipClose" />
|
||||
<div v-if="config && config.app" class="mode-bar" style="margin:20px;">
|
||||
<a-radio-group v-model="config.app.mode" button-style="solid" @change="modeChange">
|
||||
<a-tooltip placement="topLeft" title="启用测速,关闭拦截,关闭增强(不稳定,不需要安装证书,最安全)">
|
||||
<a-radio-button value="safe">
|
||||
|
@ -301,61 +303,67 @@ export default {
|
|||
</a-radio-group>
|
||||
</div>
|
||||
|
||||
<div v-if="status"
|
||||
style="margin-top:20px;display: flex; align-items:center;justify-content:space-around;flex-direction: row">
|
||||
|
||||
<div
|
||||
v-if="status"
|
||||
style="margin-top:20px;display: flex; align-items:center;justify-content:space-around;flex-direction: row"
|
||||
>
|
||||
<div style="text-align: center">
|
||||
<div class="big_button">
|
||||
<a-button shape="circle" :type="startup.type()" :loading="startup.loading" @click="startup.doClick">
|
||||
<img v-if="!startup.loading && !status.server.enabled" width="50" src="/logo/logo-simple.svg">
|
||||
<img v-if="!startup.loading && status.server.enabled" width="50" src="/logo/logo-fff.svg">
|
||||
</a-button>
|
||||
<div class="mt10">{{ status.server.enabled ? '已开启' : '已关闭' }}</div>
|
||||
|
||||
<div class="mt10">
|
||||
{{ status.server.enabled ? '已开启' : '已关闭' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :span="12">
|
||||
<a-form style="margin-top:20px" :label-col="{ span: 15 }" :wrapper-col="{ span: 9 }">
|
||||
<a-form-item v-for=" (item, key) in switchBtns" :key="key" :label="item.label">
|
||||
<a-tooltip placement="topLeft">
|
||||
<a-switch style="margin-left:10px" :loading="item.loading" :checked="item.status()" default-checked
|
||||
@change="item.doClick">
|
||||
<a-icon slot="checkedChildren" type="check"/>
|
||||
<a-icon slot="unCheckedChildren" type="close"/>
|
||||
<a-switch
|
||||
style="margin-left:10px" :loading="item.loading" :checked="item.status()" default-checked
|
||||
@change="item.doClick"
|
||||
>
|
||||
<a-icon slot="checkedChildren" type="check" />
|
||||
<a-icon slot="unCheckedChildren" type="close" />
|
||||
</a-switch>
|
||||
</a-tooltip>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<setup-ca title="安装证书" :visible.sync="setupCa.visible" @setup="handleCaSetuped"></setup-ca>
|
||||
<SetupCa title="安装证书" :visible.sync="setupCa.visible" @setup="handleCaSetuped" />
|
||||
<div slot="footer">
|
||||
<div class="star" v-if="!setting.overwall">
|
||||
<div v-if="!setting.overwall" class="star">
|
||||
<div class="donate">
|
||||
<a-tooltip placement="topLeft" title="彩蛋,点我">
|
||||
<span style="display: block;width:100px;height:50px;" @click="wantOW()"></span>
|
||||
<span style="display: block;width:100px;height:50px;" @click="wantOW()" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<div class="right"></div>
|
||||
<div class="right" />
|
||||
</div>
|
||||
<div class="star" v-if="setting.development == null || !setting.development">
|
||||
<div class="donate" @click="donateModal=true">
|
||||
<a-icon type="like" theme="outlined"/>
|
||||
<div v-if="setting.development == null || !setting.development" class="star">
|
||||
<div class="donate" @click="donateModal = true">
|
||||
<a-icon type="like" theme="outlined" />
|
||||
捐赠
|
||||
</div>
|
||||
<div class="right">
|
||||
<div>如果它解决了你的问题,请不要吝啬你的star哟!点这里
|
||||
<a-icon style="margin-right:10px;" type="arrow-right" theme="outlined"/>
|
||||
<div>
|
||||
如果它解决了你的问题,请不要吝啬你的star哟!点这里
|
||||
<a-icon style="margin-right:10px;" type="arrow-right" theme="outlined" />
|
||||
</div>
|
||||
<a @click="openExternal('https://github.com/docmirror/dev-sidecar')"><img alt="GitHub stars"
|
||||
src="https://img.shields.io/github/stars/docmirror/dev-sidecar?logo=github"></a>
|
||||
<a @click="openExternal('https://github.com/docmirror/dev-sidecar')"><img
|
||||
alt="GitHub stars"
|
||||
src="https://img.shields.io/github/stars/docmirror/dev-sidecar?logo=github"
|
||||
></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a-modal title="捐赠" v-if="setting.development == null || !setting.development" v-model="donateModal" width="550px" cancelText="不了" okText="果断支持" @ok="goDonate">
|
||||
<a-modal v-if="setting.development == null || !setting.development" v-model="donateModal" title="捐赠" width="550px" cancel-text="不了" ok-text="果断支持" @ok="goDonate">
|
||||
<div>* 本应用完全免费,如果觉得好用,可以给予捐赠。</div>
|
||||
<div>* 开源项目持续发展离不开您的支持,感谢</div>
|
||||
<div class="payQrcode">
|
||||
|
@ -363,8 +371,7 @@ export default {
|
|||
</div>
|
||||
</a-modal>
|
||||
</div>
|
||||
</ds-container>
|
||||
|
||||
</DsContainer>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
@ -97,15 +97,15 @@ export default {
|
|||
<span><code>Git.exe</code>将不代理以下仓库;可以是根地址、组织/机构地址、完整地址</span>
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button type="primary" icon="plus" @click="addNoProxyUrl()"/>
|
||||
<a-button type="primary" icon="plus" @click="addNoProxyUrl()" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10" v-for="(item,index) of noProxyUrls" :key='index'>
|
||||
<a-row v-for="(item, index) of noProxyUrls" :key="index" :gutter="10">
|
||||
<a-col :span="22">
|
||||
<a-input :disabled="item.value === false" v-model="item.key"></a-input>
|
||||
<a-input v-model="item.key" :disabled="item.value === false" />
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button type="danger" icon="minus" @click="delNoProxyUrl(item,index)"/>
|
||||
<a-button type="danger" icon="minus" @click="delNoProxyUrl(item, index)" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
|
|
|
@ -18,7 +18,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
ready () {
|
||||
return this.$api.plugin.node.getVariables().then(ret => {
|
||||
return this.$api.plugin.node.getVariables().then((ret) => {
|
||||
console.log('variables', ret)
|
||||
this.npmVariables = ret
|
||||
})
|
||||
|
@ -70,8 +70,10 @@ export default {
|
|||
</a-tag>
|
||||
</a-form-item>
|
||||
<a-form-item label="npm命令名" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input v-model="config.plugin.node.setting.command"></a-input>
|
||||
<div class="form-help">如果你的npm命令改成了其他名字,或者想设置绿色版npm程序路径,可在此处修改</div>
|
||||
<a-input v-model="config.plugin.node.setting.command" />
|
||||
<div class="form-help">
|
||||
如果你的npm命令改成了其他名字,或者想设置绿色版npm程序路径,可在此处修改
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="SSL校验" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.plugin.node.setting['strict-ssl']">
|
||||
|
@ -80,8 +82,10 @@ export default {
|
|||
npm代理启用后必须关闭
|
||||
</a-form-item>
|
||||
<a-form-item label="npm仓库镜像" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-radio-group v-model="config.plugin.node.setting.registry" @change="onSwitchRegistry"
|
||||
default-value="https://registry.npmjs.org" button-style="solid">
|
||||
<a-radio-group
|
||||
v-model="config.plugin.node.setting.registry" default-value="https://registry.npmjs.org"
|
||||
button-style="solid" @change="onSwitchRegistry"
|
||||
>
|
||||
<a-radio-button value="https://registry.npmjs.org" title="https://registry.npmjs.org">
|
||||
npmjs原生
|
||||
</a-radio-button>
|
||||
|
@ -89,36 +93,42 @@ export default {
|
|||
taobao镜像
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
<div class="form-help">设置后立即生效,即使关闭 ds 也会继续保持</div>
|
||||
<div class="form-help">
|
||||
设置后立即生效,即使关闭 ds 也会继续保持
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="yarn仓库镜像" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-radio-group v-model="config.plugin.node.setting.yarnRegistry" :default-value="'null'" @change="onSwitchYarnRegistry" button-style="solid">
|
||||
<a-radio-button :value="'null'" title="https://registry.yarnpkg.com">
|
||||
<a-radio-group v-model="config.plugin.node.setting.yarnRegistry" default-value="null" button-style="solid" @change="onSwitchYarnRegistry">
|
||||
<a-radio-button value="default" title="https://registry.yarnpkg.com">
|
||||
yarn原生
|
||||
</a-radio-button>
|
||||
<a-radio-button value="https://registry.npmmirror.com" title="https://registry.npmmirror.com">
|
||||
taobao镜像
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
<div class="form-help">设置后立即生效,即使关闭 ds 也会继续保持</div>
|
||||
<div class="form-help">
|
||||
设置后立即生效,即使关闭 ds 也会继续保持
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="镜像变量设置" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.plugin.node.startup.variables">
|
||||
自动设置,启动npm加速开关时将会设置如下环境变量
|
||||
</a-checkbox>
|
||||
<div class="form-help">某些库需要自己设置镜像变量,才能下载,比如:<code>electron</code></div>
|
||||
<a-row :gutter="10" style="margin-top: 2px" v-for="(item,index) of npmVariables" :key='index'>
|
||||
<div class="form-help">
|
||||
某些库需要自己设置镜像变量,才能下载,比如:<code>electron</code>
|
||||
</div>
|
||||
<a-row v-for="(item, index) of npmVariables" :key="index" :gutter="10" style="margin-top: 2px">
|
||||
<a-col :span="10">
|
||||
<a-input v-model="item.key" :title="item.key" readOnly></a-input>
|
||||
<a-input v-model="item.key" :title="item.key" read-only />
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<a-input v-model="item.value" :title="item.value" readOnly></a-input>
|
||||
<a-input v-model="item.value" :title="item.value" read-only />
|
||||
</a-col>
|
||||
<a-col :span="4">
|
||||
<a-icon v-if="item.exists && item.hadSet" title="已设置" style="color:green" type="check"/>
|
||||
<a-icon v-else title="还未设置" style="color:red" type="exclamation-circle"/>
|
||||
<a-icon v-if="item.exists && item.hadSet" title="已设置" style="color:green" type="check" />
|
||||
<a-icon v-else title="还未设置" style="color:red" type="exclamation-circle" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form-item>
|
||||
|
|
|
@ -152,12 +152,12 @@ export default {
|
|||
<span>PAC没有拦截到的域名,可以在此处定义;配置为<code>禁用</code>时,将不使用梯子</span>
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button type="primary" icon="plus" @click="addTarget()"/>
|
||||
<a-button type="primary" icon="plus" @click="addTarget()" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10" v-for="(item,index) of targets" :key="index">
|
||||
<a-row v-for="(item, index) of targets" :key="index" :gutter="10">
|
||||
<a-col :span="18">
|
||||
<a-input v-model="item.key"></a-input>
|
||||
<a-input v-model="item.key" />
|
||||
</a-col>
|
||||
<a-col :span="4">
|
||||
<a-select v-model="item.value" style="width:100%">
|
||||
|
@ -167,7 +167,7 @@ export default {
|
|||
</a-select>
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button type="danger" icon="minus" @click="deleteTarget(item,index)"/>
|
||||
<a-button type="danger" icon="minus" @click="deleteTarget(item, index)" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
|
@ -179,24 +179,24 @@ export default {
|
|||
<span>Nginx二层代理服务端配置</span>
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button type="primary" icon="plus" @click="addServer()"/>
|
||||
<a-button type="primary" icon="plus" @click="addServer()" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10" v-for="(item,index) of servers" :key="index">
|
||||
<a-row v-for="(item, index) of servers" :key="index" :gutter="10">
|
||||
<a-col :span="6">
|
||||
<a-input addon-before="域名" placeholder="yourdomain.com" v-model="item.key"/>
|
||||
<a-input v-model="item.key" addon-before="域名" placeholder="yourdomain.com" />
|
||||
</a-col>
|
||||
<a-col :span="5">
|
||||
<a-input addon-before="端口" placeholder="443" v-model="item.value.port"/>
|
||||
<a-input v-model="item.value.port" addon-before="端口" placeholder="443" />
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-input addon-before="路径" placeholder="xxxxxx" v-model="item.value.path"/>
|
||||
<a-input v-model="item.value.path" addon-before="路径" placeholder="xxxxxx" />
|
||||
</a-col>
|
||||
<a-col :span="5">
|
||||
<a-input addon-before="密码" type="password" placeholder="password" v-model="item.value.password"/>
|
||||
<a-input v-model="item.value.password" addon-before="密码" type="password" placeholder="password" />
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button type="danger" icon="minus" @click="deleteServer(item,index)"/>
|
||||
<a-button type="danger" icon="minus" @click="deleteServer(item, index)" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<div class="form-help">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import Plugin from '../../mixins/plugin'
|
||||
|
||||
export default {
|
||||
name: 'pip',
|
||||
name: 'Pip',
|
||||
mixins: [Plugin],
|
||||
data () {
|
||||
return {
|
||||
|
@ -37,7 +37,6 @@ export default {
|
|||
this.config.plugin.pip.setting.trustedHost = domain
|
||||
await this.apply()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -46,30 +45,32 @@ export default {
|
|||
<ds-container>
|
||||
<template slot="header">
|
||||
PIP加速
|
||||
<span style="color:#999;">
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<div v-if="config">
|
||||
<a-form layout="horizontal">
|
||||
<!-- <a-form-item label="启用PIP加速" :label-col="labelCol" :wrapper-col="wrapperCol">-->
|
||||
<!-- <a-checkbox v-model="config.plugin.pip.enabled">-->
|
||||
<!-- 随应用启动-->
|
||||
<!-- </a-checkbox>-->
|
||||
<!-- <a-tag v-if="status.plugin.pip.enabled" color="green">-->
|
||||
<!-- 当前已启动-->
|
||||
<!-- </a-tag>-->
|
||||
<!-- <a-tag v-else color="red">-->
|
||||
<!-- 当前未启动-->
|
||||
<!-- </a-tag>-->
|
||||
<!-- </a-form-item>-->
|
||||
<!-- <a-form-item label="启用PIP加速" :label-col="labelCol" :wrapper-col="wrapperCol"> -->
|
||||
<!-- <a-checkbox v-model="config.plugin.pip.enabled"> -->
|
||||
<!-- 随应用启动 -->
|
||||
<!-- </a-checkbox> -->
|
||||
<!-- <a-tag v-if="status.plugin.pip.enabled" color="green"> -->
|
||||
<!-- 当前已启动 -->
|
||||
<!-- </a-tag> -->
|
||||
<!-- <a-tag v-else color="red"> -->
|
||||
<!-- 当前未启动 -->
|
||||
<!-- </a-tag> -->
|
||||
<!-- </a-form-item> -->
|
||||
<a-form-item label="pip命令名" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input v-model="config.plugin.pip.setting.command"></a-input>
|
||||
<div class="form-help">如果你的<code>pip</code>命令改成了其他名字(如<code>pip3</code>),或想设置绿色版<code>pip</code>程序路径,可在此处修改</div>
|
||||
<a-input v-model="config.plugin.pip.setting.command" />
|
||||
<div class="form-help">
|
||||
如果你的<code>pip</code>命令改成了其他名字(如<code>pip3</code>),或想设置绿色版<code>pip</code>程序路径,可在此处修改
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="仓库镜像" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-radio-group v-model="config.plugin.pip.setting.registry" @change="onSwitchRegistry"
|
||||
default-value="https://pypi.org/simple/" button-style="solid">
|
||||
<a-radio-group
|
||||
v-model="config.plugin.pip.setting.registry" default-value="https://pypi.org/simple/"
|
||||
button-style="solid" @change="onSwitchRegistry"
|
||||
>
|
||||
<a-radio-button value="https://pypi.org/simple/" title="https://pypi.org/simple/">
|
||||
原生
|
||||
</a-radio-button>
|
||||
|
@ -104,10 +105,12 @@ export default {
|
|||
山东理工大学镜像
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
<div class="form-help">设置后立即生效,即使关闭 ds 也会继续保持</div>
|
||||
<div class="form-help">
|
||||
设置后立即生效,即使关闭 ds 也会继续保持
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="信任仓库域名" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input v-model="config.plugin.pip.setting.trustedHost"></a-input>
|
||||
<a-input v-model="config.plugin.pip.setting.trustedHost" />
|
||||
<div class="form-help">
|
||||
使用以上域名安装包时,不会进行SSL证书验证,多个域名用空格隔开<br/>
|
||||
注意:切换仓库镜像同时会修改<code>pip.ini</code>中的<code>trusted-host</code>配置,即使关闭 ds 也会继续保持
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import Plugin from '../mixins/plugin'
|
||||
|
||||
export default {
|
||||
name: 'Proxy',
|
||||
mixins: [Plugin],
|
||||
|
@ -31,11 +32,11 @@ export default {
|
|||
try {
|
||||
await this.$api.proxy.setEnableLoopback()
|
||||
} catch (e) {
|
||||
if (e.message.indexOf('EACCES') !== -1) {
|
||||
if (e.message.includes('EACCES')) {
|
||||
this.$message.error('请将DevSidecar关闭后,以管理员身份重新打开,再尝试此操作')
|
||||
return
|
||||
}
|
||||
this.$message.error('打开失败:' + e.message)
|
||||
this.$message.error(`打开失败:${e.message}`)
|
||||
}
|
||||
},
|
||||
getProxyConfig () {
|
||||
|
@ -73,13 +74,11 @@ export default {
|
|||
<ds-container>
|
||||
<template slot="header">
|
||||
系统代理设置
|
||||
<span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<div v-if="config">
|
||||
<a-form-item label="启用系统代理" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.proxy.enabled" >
|
||||
<a-checkbox v-model="config.proxy.enabled">
|
||||
随应用启动
|
||||
</a-checkbox>
|
||||
<a-tag v-if="status.proxy.enabled" color="green">
|
||||
|
@ -93,7 +92,7 @@ export default {
|
|||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="代理HTTP请求" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.proxy.proxyHttp" >
|
||||
<a-checkbox v-model="config.proxy.proxyHttp">
|
||||
是否代理HTTP请求
|
||||
</a-checkbox>
|
||||
<div class="form-help">
|
||||
|
@ -104,7 +103,7 @@ export default {
|
|||
|
||||
<!-- 以下两个功能仅windows支持,mac和linux暂不支持 -->
|
||||
<a-form-item v-if="isWindows()" label="设置环境变量" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.proxy.setEnv" >
|
||||
<a-checkbox v-model="config.proxy.setEnv">
|
||||
是否同时修改<code>HTTPS_PROXY</code>环境变量(不好用,不建议勾选)
|
||||
</a-checkbox>
|
||||
<div class="form-help">
|
||||
|
@ -113,18 +112,20 @@ export default {
|
|||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="isWindows()" label="设置loopback" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-button @click="loopbackVisible=true">去设置</a-button>
|
||||
<div class="form-help">解决<code>OneNote</code>、<code>MicrosoftStore</code>、<code>Outlook</code>等<code>UWP应用</code>开启代理后无法访问网络的问题</div>
|
||||
<a-button @click="loopbackVisible = true">去设置</a-button>
|
||||
<div class="form-help">
|
||||
解决<code>OneNote</code>、<code>MicrosoftStore</code>、<code>Outlook</code>等<code>UWP应用</code>开启代理后无法访问网络的问题
|
||||
</div>
|
||||
</a-form-item>
|
||||
|
||||
<hr/>
|
||||
<a-form-item label="排除国内域名" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.proxy.excludeDomesticDomainAllowList" >
|
||||
<a-checkbox v-model="config.proxy.excludeDomesticDomainAllowList">
|
||||
是否排除国内域名白名单
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
<a-form-item label="自动更新国内域名" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.proxy.autoUpdateDomesticDomainAllowList" >
|
||||
<a-checkbox v-model="config.proxy.autoUpdateDomesticDomainAllowList">
|
||||
是否自动更新国内域名白名单
|
||||
</a-checkbox>
|
||||
<div class="form-help">
|
||||
|
@ -133,7 +134,7 @@ export default {
|
|||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="远程国内域名地址" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input v-model="config.proxy.remoteDomesticDomainAllowListFileUrl" :title="config.proxy.remoteDomesticDomainAllowListFileUrl"></a-input>
|
||||
<a-input v-model="config.proxy.remoteDomesticDomainAllowListFileUrl" :title="config.proxy.remoteDomesticDomainAllowListFileUrl" />
|
||||
<div class="form-help">
|
||||
远程国内域名白名单文件内容可以是<code>base64</code>编码格式,也可以是未经过编码的
|
||||
</div>
|
||||
|
@ -145,15 +146,15 @@ export default {
|
|||
<span>访问的域名或IP符合下列配置时,将跳过系统代理</span>
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button type="primary" icon="plus" @click="addExcludeIp()"/>
|
||||
<a-button type="primary" icon="plus" @click="addExcludeIp()" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10" v-for="(item,index) of excludeIpList" :key='index'>
|
||||
<a-row v-for="(item, index) of excludeIpList" :key="index" :gutter="10">
|
||||
<a-col :span="22">
|
||||
<a-input :disabled="item.value === false" v-model="item.key"></a-input>
|
||||
<a-input v-model="item.key" :disabled="item.value === false" />
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button type="danger" icon="minus" @click="delExcludeIp(item,index)"/>
|
||||
<a-button type="danger" icon="minus" @click="delExcludeIp(item, index)" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form-item>
|
||||
|
@ -171,12 +172,13 @@ export default {
|
|||
:visible.sync="loopbackVisible"
|
||||
width="660px"
|
||||
height="100%"
|
||||
@close="loopbackVisible=false"
|
||||
:slots="{ title: 'title' }"
|
||||
wrapClassName="json-wrapper"
|
||||
wrap-class-name="json-wrapper"
|
||||
@close="loopbackVisible = false"
|
||||
>
|
||||
<template slot="title">
|
||||
设置Loopback <a-button style="float:right;margin-right:10px;" @click="openEnableLoopback()">打开EnableLoopback</a-button>
|
||||
设置Loopback
|
||||
<a-button style="float:right;margin-right:10px;" @click="openEnableLoopback()">打开EnableLoopback</a-button>
|
||||
</template>
|
||||
<div>
|
||||
<div>1、此设置用于解决OneNote、MicrosoftStore、Outlook等UWP应用无法访问网络的问题。</div>
|
||||
|
@ -184,8 +186,6 @@ export default {
|
|||
<div>3、注意:此操作需要<b style="color:red">DevSidecar以管理员身份启动</b>,才能打开下面的EnableLoopback设置界面</div>
|
||||
<img style="margin-top:20px;border:1px solid #eee" width="80%" src="loopback.png"/>
|
||||
</div>
|
||||
|
||||
</a-drawer>
|
||||
</ds-container>
|
||||
|
||||
</template>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script>
|
||||
import vueJsonEditor from 'vue-json-editor-fix-cn'
|
||||
import Plugin from '../mixins/plugin'
|
||||
import _ from 'lodash'
|
||||
import VueJsonEditor from 'vue-json-editor-fix-cn'
|
||||
import Plugin from '../mixins/plugin'
|
||||
|
||||
export default {
|
||||
name: 'Server',
|
||||
components: {
|
||||
vueJsonEditor
|
||||
VueJsonEditor
|
||||
},
|
||||
mixins: [Plugin],
|
||||
data () {
|
||||
|
@ -17,11 +17,6 @@ export default {
|
|||
whiteList: []
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
mounted () {
|
||||
this.registerSpeedTestEvent()
|
||||
},
|
||||
computed: {
|
||||
speedDnsOptions () {
|
||||
const options = []
|
||||
|
@ -37,6 +32,11 @@ export default {
|
|||
return options
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
mounted () {
|
||||
this.registerSpeedTestEvent()
|
||||
},
|
||||
methods: {
|
||||
async onCrtSelect () {
|
||||
const value = await this.$api.fileSelector.open()
|
||||
|
@ -122,7 +122,7 @@ export default {
|
|||
},
|
||||
async openLog () {
|
||||
const dir = await this.$api.info.getConfigDir()
|
||||
this.$api.ipc.openPath(dir + '/logs/')
|
||||
this.$api.ipc.openPath(`${dir}/logs/`)
|
||||
},
|
||||
getSpeedTestConfig () {
|
||||
return this.config.server.dns.speedTest
|
||||
|
@ -178,19 +178,17 @@ export default {
|
|||
<ds-container>
|
||||
<template slot="header">
|
||||
加速服务设置
|
||||
<span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<div style="height: 100%" class="json-wrapper">
|
||||
<a-tabs
|
||||
v-if="config"
|
||||
default-active-key="1"
|
||||
tab-position="left"
|
||||
:style="{ height: '100%' }"
|
||||
v-if="config"
|
||||
@change="handleTabChange"
|
||||
>
|
||||
<a-tab-pane tab="基本设置" key="1">
|
||||
<a-tab-pane key="1" tab="基本设置">
|
||||
<div style="padding-right:10px">
|
||||
<a-form-item label="代理服务:" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.server.enabled">
|
||||
|
@ -205,148 +203,174 @@ export default {
|
|||
<a-button class="md-mr-10" icon="profile" @click="openLog()">日志</a-button>
|
||||
</a-form-item>
|
||||
<a-form-item label="绑定IP" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input v-model="config.server.host"/>
|
||||
<div class="form-help">你可以设置为<code>0.0.0.0</code>,让其他电脑可以使用此代理服务</div>
|
||||
<a-input v-model="config.server.host" />
|
||||
<div class="form-help">
|
||||
你可以设置为<code>0.0.0.0</code>,让其他电脑可以使用此代理服务
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="代理端口" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input-number v-model="config.server.port" :min="0" :max="65535"/>
|
||||
<div class="form-help">修改后需要重启应用</div>
|
||||
<a-input-number v-model="config.server.port" :min="0" :max="65535" />
|
||||
<div class="form-help">
|
||||
修改后需要重启应用
|
||||
</div>
|
||||
</a-form-item>
|
||||
<hr/>
|
||||
<a-form-item label="全局校验SSL" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.server.setting.NODE_TLS_REJECT_UNAUTHORIZED">
|
||||
NODE_TLS_REJECT_UNAUTHORIZED
|
||||
</a-checkbox>
|
||||
<div class="form-help">高风险操作,没有特殊情况请勿关闭</div>
|
||||
<div class="form-help">
|
||||
高风险操作,没有特殊情况请勿关闭
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="代理校验SSL" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.server.setting.verifySsl">
|
||||
校验加速目标网站的ssl证书
|
||||
</a-checkbox>
|
||||
<div class="form-help">如果目标网站证书有问题,但你想强行访问,可以临时关闭此项</div>
|
||||
<div class="form-help">
|
||||
如果目标网站证书有问题,但你想强行访问,可以临时关闭此项
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="根证书" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input-search addon-before="Cert" enter-button="选择" @search="onCrtSelect"
|
||||
v-model="config.server.setting.rootCaFile.certPath"
|
||||
:title="config.server.setting.rootCaFile.certPath"/>
|
||||
<a-input-search addon-before="Key" enter-button="选择" @search="onKeySelect"
|
||||
v-model="config.server.setting.rootCaFile.keyPath"
|
||||
:title="config.server.setting.rootCaFile.keyPath"/>
|
||||
<a-input-search
|
||||
v-model="config.server.setting.rootCaFile.certPath" addon-before="Cert" enter-button="选择"
|
||||
:title="config.server.setting.rootCaFile.certPath"
|
||||
@search="onCrtSelect"
|
||||
/>
|
||||
<a-input-search
|
||||
v-model="config.server.setting.rootCaFile.keyPath" addon-before="Key" enter-button="选择"
|
||||
:title="config.server.setting.rootCaFile.keyPath"
|
||||
@search="onKeySelect"
|
||||
/>
|
||||
</a-form-item>
|
||||
<hr/>
|
||||
<a-form-item label="启用拦截" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.server.intercept.enabled">
|
||||
启用拦截
|
||||
</a-checkbox>
|
||||
<div class="form-help">关闭拦截,且关闭功能增强时,就不需要安装根证书,退化为安全模式</div>
|
||||
<div class="form-help">
|
||||
关闭拦截,且关闭功能增强时,就不需要安装根证书,退化为安全模式
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="启用脚本" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="config.server.setting.script.enabled">
|
||||
允许插入并运行脚本
|
||||
</a-checkbox>
|
||||
<div class="form-help">关闭后,<code>Github油猴脚本</code>也将关闭</div>
|
||||
<div class="form-help">
|
||||
关闭后,<code>Github油猴脚本</code>也将关闭
|
||||
</div>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="拦截设置" key="2">
|
||||
<vue-json-editor style="height:100%" ref="editor" v-model="config.server.intercepts" mode="code"
|
||||
:show-btns="false" :expandedOnStart="true"></vue-json-editor>
|
||||
<a-tab-pane key="2" tab="拦截设置">
|
||||
<VueJsonEditor
|
||||
ref="editor" v-model="config.server.intercepts" style="height:100%" mode="code"
|
||||
:show-btns="false" :expanded-on-start="true"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="超时时间设置" key="3">
|
||||
<a-tab-pane key="3" tab="超时时间设置">
|
||||
<div style="height:100%;display:flex;flex-direction:column;padding-right:10px">
|
||||
<a-form-item label="默认超时时间" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
请求:<a-input-number v-model="config.server.setting.defaultTimeout" :step="1000" :min="1000"/> ms,对应<code>timeout</code>配置<br/>
|
||||
连接:<a-input-number v-model="config.server.setting.defaultKeepAliveTimeout" :step="1000" :min="1000"/> ms,对应<code>keepAliveTimeout</code>配置
|
||||
请求:<a-input-number v-model="config.server.setting.defaultTimeout" :step="1000" :min="1000" /> ms,对应<code>timeout</code>配置<br>
|
||||
连接:<a-input-number v-model="config.server.setting.defaultKeepAliveTimeout" :step="1000" :min="1000" /> ms,对应<code>keepAliveTimeout</code>配置
|
||||
</a-form-item>
|
||||
<hr style="margin-bottom:15px"/>
|
||||
<div>这里指定域名的超时时间:<span class="form-help">(域名配置可使用通配符或正则)</span></div>
|
||||
<vue-json-editor style="flex-grow:1;min-height:300px;margin-top:10px" ref="editor" v-model="config.server.setting.timeoutMapping" mode="code"
|
||||
:show-btns="false" :expandedOnStart="true"></vue-json-editor>
|
||||
<VueJsonEditor
|
||||
ref="editor" v-model="config.server.setting.timeoutMapping" style="flex-grow:1;min-height:300px;margin-top:10px" mode="code"
|
||||
:show-btns="false" :expanded-on-start="true"
|
||||
/>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="域名白名单" key="4">
|
||||
<a-tab-pane key="4" tab="域名白名单">
|
||||
<a-row style="margin-top:10px">
|
||||
<a-col span="19">
|
||||
<div>这里配置的域名不会通过代理</div>
|
||||
</a-col>
|
||||
<a-col span="3">
|
||||
<a-button style="margin-left:8px" type="primary" icon="plus" @click="addWhiteList()"/>
|
||||
<a-button style="margin-left:8px" type="primary" icon="plus" @click="addWhiteList()" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10" style="margin-top: 5px" v-for="(item,index) of whiteList" :key='index'>
|
||||
<a-row v-for="(item, index) of whiteList" :key="index" :gutter="10" style="margin-top: 5px">
|
||||
<a-col :span="19">
|
||||
<a-input :disabled="item.value === false" v-model="item.key"></a-input>
|
||||
<a-input v-model="item.key" :disabled="item.value === false" />
|
||||
</a-col>
|
||||
<a-col :span="3">
|
||||
<a-button v-if="item.value !== false" type="danger" icon="minus" @click="deleteWhiteList(item,index)"/>
|
||||
<a-button v-if="item.value !== false" type="danger" icon="minus" @click="deleteWhiteList(item, index)" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="自动兼容程序" key="5">
|
||||
<a-tab-pane key="5" tab="自动兼容程序">
|
||||
<div style="height:100%;display:flex;flex-direction:column">
|
||||
<div>
|
||||
说明:<code>自动兼容程序</code>会自动根据错误信息进行兼容性调整,并将兼容设置保存在 <code>~/.dev-sidecar/automaticCompatibleConfig.json</code> 文件中。但并不是所有的兼容设置都是正确的,所以需要通过以下配置来覆盖错误的兼容设置。
|
||||
</div>
|
||||
<vue-json-editor style="flex-grow:1;min-height:300px;margin-top:10px;" ref="editor" v-model="config.server.compatible" mode="code"
|
||||
:show-btns="false" :expandedOnStart="true"></vue-json-editor>
|
||||
<VueJsonEditor
|
||||
ref="editor" v-model="config.server.compatible" style="flex-grow:1;min-height:300px;margin-top:10px;" mode="code"
|
||||
:show-btns="false" :expanded-on-start="true"
|
||||
/>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="IP预设置" key="6">
|
||||
<a-tab-pane key="6" tab="IP预设置">
|
||||
<div style="height:100%;display:flex;flex-direction:column">
|
||||
<div>
|
||||
提示:<code>IP预设置</code>功能,优先级高于 <code>DNS设置</code>
|
||||
<span class="form-help">(域名配置可使用通配符或正则)</span>
|
||||
</div>
|
||||
<vue-json-editor style="flex-grow:1;min-height:300px;margin-top:10px;" ref="editor" v-model="config.server.preSetIpList" mode="code"
|
||||
:show-btns="false" :expandedOnStart="true"></vue-json-editor>
|
||||
<VueJsonEditor
|
||||
ref="editor" v-model="config.server.preSetIpList" style="flex-grow:1;min-height:300px;margin-top:10px;" mode="code"
|
||||
:show-btns="false" :expanded-on-start="true"
|
||||
/>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="DNS服务管理" key="7">
|
||||
<vue-json-editor style="height:100%" ref="editor" v-model="config.server.dns.providers" mode="code"
|
||||
:show-btns="false" :expandedOnStart="true"></vue-json-editor>
|
||||
<a-tab-pane key="7" tab="DNS服务管理">
|
||||
<VueJsonEditor
|
||||
ref="editor" v-model="config.server.dns.providers" style="height:100%" mode="code"
|
||||
:show-btns="false" :expanded-on-start="true"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="DNS设置" key="8">
|
||||
<a-tab-pane key="8" tab="DNS设置">
|
||||
<div>
|
||||
<a-row style="margin-top:10px">
|
||||
<a-col span="19">
|
||||
<div>这里配置哪些域名需要通过国外DNS服务器获取IP进行访问</div>
|
||||
</a-col>
|
||||
<a-col span="3">
|
||||
<a-button style="margin-left:8px" type="primary" icon="plus" @click="addDnsMapping()"/>
|
||||
<a-button style="margin-left:8px" type="primary" icon="plus" @click="addDnsMapping()" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10" style="margin-top: 5px" v-for="(item,index) of dnsMappings" :key='index'>
|
||||
<a-row v-for="(item, index) of dnsMappings" :key="index" :gutter="10" style="margin-top: 5px">
|
||||
<a-col :span="14">
|
||||
<a-input :disabled="item.value === false" v-model="item.key"></a-input>
|
||||
<a-input v-model="item.key" :disabled="item.value === false" />
|
||||
</a-col>
|
||||
<a-col :span="5">
|
||||
<a-select :disabled="item.value === false" v-model="item.value" style="width: 100%">
|
||||
<a-select v-model="item.value" :disabled="item.value === false" style="width: 100%">
|
||||
<a-select-option v-for="(item) of speedDnsOptions" :key="item.value" :value="item.value">
|
||||
{{ item.value }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-col>
|
||||
<a-col :span="3">
|
||||
<a-button v-if="item.value !== false" type="danger" icon="minus" @click="deleteDnsMapping(item,index)"/>
|
||||
<a-button v-if="item.value === false" type="primary" icon="checked" @click="restoreDefDnsMapping(item,index)"/>
|
||||
<a-button v-if="item.value !== false" type="danger" icon="minus" @click="deleteDnsMapping(item, index)" />
|
||||
<a-button v-if="item.value === false" type="primary" icon="checked" @click="restoreDefDnsMapping(item, index)" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="IP测速" key="9">
|
||||
<a-tab-pane key="9" tab="IP测速">
|
||||
<div class="ip-tester" style="padding-right: 10px">
|
||||
<a-alert type="info" message="对从DNS获取到的IP进行测速,使用速度最快的IP进行访问(注意:对使用了增强功能的域名没啥用)"></a-alert>
|
||||
<a-alert type="info" message="对从DNS获取到的IP进行测速,使用速度最快的IP进行访问(注意:对使用了增强功能的域名没啥用)" />
|
||||
<a-form-item label="开启DNS测速" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-checkbox v-model="getSpeedTestConfig().enabled">
|
||||
启用
|
||||
</a-checkbox>
|
||||
</a-form-item>
|
||||
<a-form-item label="自动测试间隔" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input-number v-model="getSpeedTestConfig().interval" :step="1000" :min="1"/> ms
|
||||
<a-input-number v-model="getSpeedTestConfig().interval" :step="1000" :min="1" /> ms
|
||||
</a-form-item>
|
||||
<!--<a-form-item label="慢速IP阈值" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<!-- <a-form-item label="慢速IP阈值" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input-number v-model="config.server.setting.lowSpeedDelay" :step="10" :min="100"/> ms
|
||||
</a-form-item>-->
|
||||
</a-form-item> -->
|
||||
<div>使用以下DNS获取IP进行测速</div>
|
||||
<a-row style="margin-top:10px">
|
||||
<a-col span="24">
|
||||
|
@ -361,20 +385,22 @@ export default {
|
|||
以下域名在启动后立即进行测速,其他域名在第一次访问时才测速
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button style="margin-left:10px" type="primary" icon="plus" @click="addSpeedHostname()"/>
|
||||
<a-button style="margin-left:10px" type="primary" icon="plus" @click="addSpeedHostname()" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10" style="margin-top: 5px" v-for="(item,index) of getSpeedTestConfig().hostnameList"
|
||||
:key='index'>
|
||||
<a-row
|
||||
v-for="(item, index) of getSpeedTestConfig().hostnameList" :key="index" :gutter="10"
|
||||
style="margin-top: 5px"
|
||||
>
|
||||
<a-col :span="21">
|
||||
<a-input v-model="getSpeedTestConfig().hostnameList[index]"/>
|
||||
<a-input v-model="getSpeedTestConfig().hostnameList[index]" />
|
||||
</a-col>
|
||||
<a-col :span="2">
|
||||
<a-button style="margin-left:10px" type="danger" icon="minus" @click="delSpeedHostname(item,index)"/>
|
||||
<a-button style="margin-left:10px" type="danger" icon="minus" @click="delSpeedHostname(item, index)" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-divider/>
|
||||
<a-divider />
|
||||
<a-row :gutter="10" class="mt10">
|
||||
<a-col span="24">
|
||||
<a-button type="primary" icon="plus" @click="reSpeedTest()">立即重新测速</a-button>
|
||||
|
@ -383,14 +409,16 @@ export default {
|
|||
</a-row>
|
||||
|
||||
<a-row :gutter="20">
|
||||
<a-col span="12" v-for="(item,key) of speedTestList" :key='key'>
|
||||
<a-col v-for="(item, key) of speedTestList" :key="key" span="12">
|
||||
<a-card size="small" class="md-mt-10" :title="key">
|
||||
<a slot="extra" href="#">
|
||||
<a-icon v-if="item.alive.length>0" type="check"/>
|
||||
<a-icon v-else type="info-circle"/>
|
||||
<a-icon v-if="item.alive.length > 0" type="check" />
|
||||
<a-icon v-else type="info-circle" />
|
||||
</a>
|
||||
<a-tag style="margin:2px;" v-for="(element,index) of item.backupList" :title="element.dns"
|
||||
:color="element.time?(element.time>config.server.setting.lowSpeedDelay?'orange':'green'):'red'" :key='index'>
|
||||
<a-tag
|
||||
v-for="(element, index) of item.backupList" :key="index" style="margin:2px;"
|
||||
:title="element.dns" :color="element.time ? (element.time > config.server.setting.lowSpeedDelay ? 'orange' : 'green') : 'red'"
|
||||
>
|
||||
{{ element.host }} {{ element.time }}{{ element.time ? 'ms' : '' }} {{ element.dns }}
|
||||
</a-tag>
|
||||
</a-card>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import Plugin from '../mixins/plugin'
|
||||
import { ipcRenderer } from 'electron'
|
||||
import Plugin from '../mixins/plugin'
|
||||
|
||||
export default {
|
||||
name: 'Setting',
|
||||
|
@ -28,7 +28,7 @@ export default {
|
|||
},
|
||||
async openLog () {
|
||||
const dir = await this.$api.info.getConfigDir()
|
||||
this.$api.ipc.openPath(dir + '/logs/')
|
||||
this.$api.ipc.openPath(`${dir}/logs/`)
|
||||
},
|
||||
getEventKey (event) {
|
||||
// 忽略以下键
|
||||
|
@ -130,7 +130,7 @@ export default {
|
|||
async disableBeforeInputEvent () {
|
||||
clearTimeout(window.enableBeforeInputEventTimeout)
|
||||
window.config.disableBeforeInputEvent = true
|
||||
window.enableBeforeInputEventTimeout = setTimeout(function () {
|
||||
window.enableBeforeInputEventTimeout = setTimeout(() => {
|
||||
window.config.disableBeforeInputEvent = false
|
||||
}, 2000)
|
||||
},
|
||||
|
@ -158,12 +158,18 @@ export default {
|
|||
|
||||
// 判断 Ctrl、Alt、Shift、Window 按钮是否已按下,如果已按下,则拼接键值
|
||||
let shortcut = event.ctrlKey ? 'Ctrl + ' : ''
|
||||
if (event.altKey) shortcut += 'Alt + '
|
||||
if (event.shiftKey) shortcut += 'Shift + '
|
||||
if (event.metaKey) shortcut += 'Meta + '
|
||||
if (event.altKey) {
|
||||
shortcut += 'Alt + '
|
||||
}
|
||||
if (event.shiftKey) {
|
||||
shortcut += 'Shift + '
|
||||
}
|
||||
if (event.metaKey) {
|
||||
shortcut += 'Meta + '
|
||||
}
|
||||
|
||||
// 如果以上按钮都没有按下,并且当前键不是F1~F4、F6~F11时,则直接返回(注:F5已经是刷新页面快捷键、F12已经是打开DevTools的快捷键了)
|
||||
if (shortcut === '' && !key.match(/^F([12346789]|1[01])$/g)) {
|
||||
if (shortcut === '' && !key.match(/^F([1-46-9]|1[01])$/g)) {
|
||||
this.config.app.showHideShortcut = '无'
|
||||
return
|
||||
}
|
||||
|
@ -250,7 +256,7 @@ export default {
|
|||
this.$confirm({
|
||||
title: '确定要恢复出厂设置吗?',
|
||||
width: 610,
|
||||
content: h =>
|
||||
content: (h) => (
|
||||
<div class="restore-factory-settings">
|
||||
<hr/>
|
||||
<p>
|
||||
|
@ -267,7 +273,8 @@ export default {
|
|||
2. 将该备份文件重命名为<span>config.json</span>,再重启软件即可恢复个性化配置。
|
||||
</div>
|
||||
</p>
|
||||
</div>,
|
||||
</div>
|
||||
),
|
||||
cancelText: '取消',
|
||||
okText: '确定',
|
||||
onOk: async () => {
|
||||
|
@ -296,8 +303,6 @@ export default {
|
|||
<ds-container>
|
||||
<template slot="header">
|
||||
设置
|
||||
<span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<div v-if="config">
|
||||
|
@ -330,10 +335,10 @@ export default {
|
|||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="共享远程配置地址" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input v-model="config.app.remoteConfig.url" :title="config.app.remoteConfig.url"></a-input>
|
||||
<a-input v-model="config.app.remoteConfig.url" :title="config.app.remoteConfig.url" />
|
||||
</a-form-item>
|
||||
<a-form-item label="个人远程配置地址" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input v-model="config.app.remoteConfig.personalUrl" :title="config.app.remoteConfig.personalUrl"></a-input>
|
||||
<a-input v-model="config.app.remoteConfig.personalUrl" :title="config.app.remoteConfig.personalUrl" />
|
||||
</a-form-item>
|
||||
<a-form-item label="重载远程配置" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-button :disabled="config.app.remoteConfig.enabled === false" :loading="reloadLoading" icon="sync" @click="reloadRemoteConfig()">重载远程配置</a-button>
|
||||
|
@ -345,10 +350,10 @@ export default {
|
|||
<hr/>
|
||||
<a-form-item label="主题设置" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-radio-group v-model="config.app.theme" default-value="light" button-style="solid">
|
||||
<a-radio-button :value="'light'" title="light">
|
||||
<a-radio-button value="light" title="light">
|
||||
亮色
|
||||
</a-radio-button>
|
||||
<a-radio-button :value="'dark'" title="dark">
|
||||
<a-radio-button value="dark" title="dark">
|
||||
暗色
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
|
@ -384,7 +389,7 @@ export default {
|
|||
</a-form-item>
|
||||
<hr/>
|
||||
<a-form-item label="打开窗口快捷键" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input v-model="config.app.showHideShortcut" @change="shortcutChange" @keydown="shortcutKeyDown" @keyup="shortcutKeyUp"></a-input>
|
||||
<a-input v-model="config.app.showHideShortcut" @change="shortcutChange" @keydown="shortcutKeyDown" @keyup="shortcutKeyUp" />
|
||||
<div class="form-help">
|
||||
部分快捷键已被占用:F5=刷新页面,F12=开发者工具(DevTools)
|
||||
</div>
|
||||
|
@ -403,8 +408,8 @@ export default {
|
|||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item label="启动时窗口大小" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-input-number v-model="config.app.windowSize.width" :step="50" :min="600" :max="2400"/> ×
|
||||
<a-input-number v-model="config.app.windowSize.height" :step="50" :min="500" :max="2000"/>
|
||||
<a-input-number v-model="config.app.windowSize.width" :step="50" :min="600" :max="2400" /> ×
|
||||
<a-input-number v-model="config.app.windowSize.height" :step="50" :min="500" :max="2000" />
|
||||
</a-form-item>
|
||||
<hr/>
|
||||
<a-form-item label="自动检查更新" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
|
@ -442,5 +447,4 @@ export default {
|
|||
</div>
|
||||
</template>
|
||||
</ds-container>
|
||||
|
||||
</template>
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
import Index from '../pages/index'
|
||||
import Server from '../pages/server'
|
||||
import Proxy from '../pages/proxy'
|
||||
import Setting from '../pages/setting'
|
||||
|
||||
import Node from '../pages/plugin/node'
|
||||
import Git from '../pages/plugin/git'
|
||||
import Pip from '../pages/plugin/pip'
|
||||
import Overwall from '../pages/plugin/overwall'
|
||||
import Setting from '../pages/setting'
|
||||
|
||||
const routes = [
|
||||
{ path: '/', redirect: '/index' },
|
||||
{ path: '/index', component: Index },
|
||||
{ path: '/server', component: Server },
|
||||
{ path: '/proxy', component: Proxy },
|
||||
{ path: '/setting', component: Setting },
|
||||
{ path: '/plugin/node', component: Node },
|
||||
{ path: '/plugin/git', component: Git },
|
||||
{ path: '/plugin/pip', component: Pip },
|
||||
{ path: '/plugin/overwall', component: Overwall },
|
||||
{ path: '/setting', component: Setting }
|
||||
|
||||
{ path: '/plugin/overwall', component: Overwall }
|
||||
]
|
||||
|
||||
export default routes
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
|
||||
const publishUrl = process.env.VUE_APP_PUBLISH_URL
|
||||
const publishProvider = process.env.VUE_APP_PUBLISH_PROVIDER
|
||||
console.log('Publish url:', publishUrl)
|
||||
|
||||
/**
|
||||
* @type {import('@vue/cli-service').ProjectOptions}
|
||||
*/
|
||||
module.exports = {
|
||||
pages: {
|
||||
index: {
|
||||
|
@ -11,7 +16,7 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
configureWebpack: (config) => {
|
||||
const configNew = {
|
||||
return {
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({ 'global.GENTLY': true })
|
||||
],
|
||||
|
@ -28,7 +33,6 @@ module.exports = {
|
|||
]
|
||||
}
|
||||
}
|
||||
return configNew
|
||||
},
|
||||
pluginOptions: {
|
||||
electronBuilder: {
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
const mitmproxy = require('./lib/proxy')
|
||||
const ProxyOptions = require('./options')
|
||||
const proxyConfig = require('./lib/proxy/common/config')
|
||||
const speedTest = require('./lib/speed/index.js')
|
||||
const ProxyOptions = require('./options')
|
||||
const log = require('./utils/util.log')
|
||||
const { fireError, fireStatus } = require('./utils/util.process')
|
||||
const speedTest = require('./lib/speed/index.js')
|
||||
|
||||
let servers = []
|
||||
|
||||
function registerProcessListener () {
|
||||
process.on('message', function (msg) {
|
||||
process.on('message', (msg) => {
|
||||
log.info('child get msg:', JSON.stringify(msg))
|
||||
if (msg.type === 'action') {
|
||||
api[msg.event.key](msg.event.params)
|
||||
|
@ -22,7 +23,7 @@ function registerProcessListener () {
|
|||
})
|
||||
|
||||
// 避免异常崩溃
|
||||
process.on('uncaughtException', function (err) {
|
||||
process.on('uncaughtException', (err) => {
|
||||
if (err.code === 'ECONNABORTED') {
|
||||
// log.error(err.errno)
|
||||
return
|
||||
|
@ -37,7 +38,7 @@ function registerProcessListener () {
|
|||
process.on('uncaughtExceptionMonitor', (err, origin) => {
|
||||
log.info('Process uncaughtExceptionMonitor:', err, origin)
|
||||
})
|
||||
process.on('exit', function (code, signal) {
|
||||
process.on('exit', (code, signal) => {
|
||||
log.info('代理服务进程被关闭:', code, signal)
|
||||
})
|
||||
process.on('beforeExit', (code, signal) => {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
const LRU = require('lru-cache')
|
||||
const cacheSize = 1024
|
||||
const log = require('../../utils/util.log')
|
||||
|
||||
const cacheSize = 1024
|
||||
|
||||
class ChoiceCache {
|
||||
constructor () {
|
||||
this.cache = new LRU(cacheSize)
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
const LRU = require('lru-cache')
|
||||
// const { isIP } = require('validator')
|
||||
const log = require('../../utils/util.log')
|
||||
const { DynamicChoice } = require('../choice/index')
|
||||
|
||||
const cacheSize = 1024
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
// function _isIP (v) {
|
||||
// return v && isIP(v)
|
||||
// }
|
||||
|
||||
class IpCache extends DynamicChoice {
|
||||
constructor (hostname) {
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
const { promisify } = require('util')
|
||||
const doh = require('dns-over-http')
|
||||
const BaseDNS = require('./base')
|
||||
const log = require('../../utils/util.log')
|
||||
const dohQueryAsync = promisify(doh.query)
|
||||
const matchUtil = require('../../utils/util.match')
|
||||
const BaseDNS = require('./base')
|
||||
|
||||
const dohQueryAsync = promisify(doh.query)
|
||||
|
||||
function mapToList (ipMap) {
|
||||
const ipList = []
|
||||
for (const key in ipMap) {
|
||||
if (!ipMap[key]) continue
|
||||
if (!ipMap[key]) {
|
||||
continue
|
||||
}
|
||||
ipList.push(ipMap[key])
|
||||
}
|
||||
return ipList
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const DNSOverTLS = require('./tls.js')
|
||||
const matchUtil = require('../../utils/util.match')
|
||||
const DNSOverHTTPS = require('./https.js')
|
||||
const DNSOverIpAddress = require('./ipaddress.js')
|
||||
const DNSOverPreSetIpList = require('./preset.js')
|
||||
const matchUtil = require('../../utils/util.match')
|
||||
const DNSOverTLS = require('./tls.js')
|
||||
|
||||
module.exports = {
|
||||
initDNS (dnsProviders, preSetIpList) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const BaseDNS = require('./base')
|
||||
const axios = require('axios')
|
||||
const log = require('../../utils/util.log')
|
||||
const BaseDNS = require('./base')
|
||||
|
||||
module.exports = class DNSOverIpAddress extends BaseDNS {
|
||||
async _lookup (hostname) {
|
||||
const url = `https://${hostname}.ipaddress.com`
|
||||
|
@ -8,7 +9,7 @@ module.exports = class DNSOverIpAddress extends BaseDNS {
|
|||
// const res = fs.readFileSync(path.resolve(__dirname, './data.txt')).toString()
|
||||
const res = await axios.get(url)
|
||||
if (res.status !== 200 && res.status !== 201) {
|
||||
log.info(`[dns] get ${hostname} ipaddress: error:${res}`)
|
||||
log.error(`[dns] get ${hostname} ipaddress: error: ${res}`)
|
||||
return
|
||||
}
|
||||
const ret = res.data
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
module.exports = {
|
||||
lookup () {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
const BaseDNS = require('./base')
|
||||
const matchUtil = require('../../utils/util.match')
|
||||
const BaseDNS = require('./base')
|
||||
|
||||
function mapToList (ipMap) {
|
||||
const ipList = []
|
||||
for (const key in ipMap) {
|
||||
if (!ipMap[key]) continue
|
||||
if (!ipMap[key]) {
|
||||
continue
|
||||
}
|
||||
ipList.push(ipMap[key])
|
||||
}
|
||||
return ipList
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const dnstls = require('dns-over-tls')
|
||||
const BaseDNS = require('./base')
|
||||
const log = require('../../utils/util.log')
|
||||
const BaseDNS = require('./base')
|
||||
|
||||
module.exports = class DNSOverTLS extends BaseDNS {
|
||||
async _lookup (hostname) {
|
||||
const { answers } = await dnstls.query(hostname)
|
||||
|
|
|
@ -9,8 +9,8 @@ module.exports = {
|
|||
'DS-Interceptor': 'abort'
|
||||
})
|
||||
res.write(
|
||||
'DevSidecar 403: Request abort.\r\n\r\n' +
|
||||
' This request is matched by abort intercept.\r\n' +
|
||||
'DevSidecar 403: Request abort.\n\n' +
|
||||
' This request is matched by abort intercept.\n' +
|
||||
' 因配置abort拦截器,本请求直接返回403禁止访问。'
|
||||
)
|
||||
res.end()
|
||||
|
|
|
@ -22,13 +22,13 @@ function getTomorrow () {
|
|||
// }
|
||||
|
||||
const AipOcrClient = require('baidu-aip-sdk').ocr
|
||||
|
||||
const AipOcrClientMap = {}
|
||||
const apis = [
|
||||
'accurateBasic', // 调用通用文字识别(高精度版)
|
||||
'accurate', // 调用通用文字识别(含位置高精度版)
|
||||
'handwriting' // 手写文字识别
|
||||
]
|
||||
|
||||
const limitMap = {}
|
||||
|
||||
function createBaiduOcrClient (config) {
|
||||
|
@ -57,7 +57,9 @@ function getConfig (interceptOpt, tryCount, log) {
|
|||
}
|
||||
|
||||
// 避免count值过大,造成问题
|
||||
if (count >= 100000) count = 0
|
||||
if (count >= 100000) {
|
||||
count = 0
|
||||
}
|
||||
} else {
|
||||
config = interceptOpt.baiduOcr
|
||||
tryCount = null // 将tryCount设置为null代表只有一个配置
|
||||
|
@ -95,13 +97,13 @@ function getConfig (interceptOpt, tryCount, log) {
|
|||
}
|
||||
|
||||
function limitConfig (id, api) {
|
||||
const key = id + '_' + api
|
||||
const key = `${id}_${api}`
|
||||
limitMap[key] = getTomorrow()
|
||||
// limitMap[key] = Date.now() + 5000 // 测试用,5秒后解禁
|
||||
}
|
||||
|
||||
function checkIsLimitConfig (id, api) {
|
||||
const key = id + '_' + api
|
||||
const key = `${id}_${api}`
|
||||
const limitTime = limitMap[key]
|
||||
return limitTime && limitTime > Date.now()
|
||||
}
|
||||
|
@ -154,7 +156,7 @@ module.exports = {
|
|||
...(config.options || {})
|
||||
}
|
||||
log.info('发起百度ocr请求', req.hostname)
|
||||
client[config.api || apis[0]](imageBase64, options).then(function (result) {
|
||||
client[config.api || apis[0]](imageBase64, options).then((result) => {
|
||||
if (result.error_code != null) {
|
||||
log.error('baiduOcr error:', result)
|
||||
if (result.error_code === 17) {
|
||||
|
@ -169,13 +171,17 @@ module.exports = {
|
|||
res.writeHead(200, headers)
|
||||
res.write(JSON.stringify(result)) // 格式如:{"words_result":[{"words":"6525"}],"words_result_num":1,"log_id":1818877093747960000}
|
||||
res.end()
|
||||
if (next) next() // 异步执行完继续next
|
||||
}).catch(function (err) {
|
||||
if (next) {
|
||||
next() // 异步执行完继续next
|
||||
}
|
||||
}).catch((err) => {
|
||||
log.info('baiduOcr error:', err)
|
||||
res.writeHead(200, headers)
|
||||
res.write('{"error_code": 999500, "error_msg": "' + err + '"}') // 格式如:{"words_result":[{"words":"6525"}],"words_result_num":1,"log_id":1818877093747960000}
|
||||
res.write(`{"error_code": 999500, "error_msg": "${err}"}`) // 格式如:{"words_result":[{"words":"6525"}],"words_result_num":1,"log_id":1818877093747960000}
|
||||
res.end()
|
||||
if (next) next() // 异步执行完继续next
|
||||
if (next) {
|
||||
next() // 异步执行完继续next
|
||||
}
|
||||
})
|
||||
|
||||
log.info('proxy baiduOcr: hostname:', req.hostname)
|
||||
|
|
|
@ -44,7 +44,7 @@ function getLastModifiedTimeFromIfModifiedSince (rOptions, log) {
|
|||
return new Date(lastModified).getTime()
|
||||
} catch (e) {
|
||||
// 为数字时,直接返回
|
||||
if (/\\d+/g.test(lastModified)) {
|
||||
if (/\\d+/.test(lastModified)) {
|
||||
return lastModified - 0
|
||||
}
|
||||
|
||||
|
@ -66,12 +66,12 @@ module.exports = {
|
|||
|
||||
// 获取 Cache-Control 用于判断是否禁用缓存
|
||||
const cacheControl = rOptions.headers['cache-control']
|
||||
if (cacheControl && (cacheControl.indexOf('no-cache') >= 0 || cacheControl.indexOf('no-store') >= 0)) {
|
||||
if (cacheControl && (cacheControl.includes('no-cache') || cacheControl.includes('no-store'))) {
|
||||
return // 当前请求指定要禁用缓存,跳过当前拦截器
|
||||
}
|
||||
// 获取 Pragma 用于判断是否禁用缓存
|
||||
const pragma = rOptions.headers.pragma
|
||||
if (pragma && (pragma.indexOf('no-cache') >= 0 || pragma.indexOf('no-store') >= 0)) {
|
||||
if (pragma && (pragma.includes('no-cache') || pragma.includes('no-store'))) {
|
||||
return // 当前请求指定要禁用缓存,跳过当前拦截器
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ module.exports = {
|
|||
|
||||
// 缓存未过期,直接拦截请求并响应304
|
||||
res.writeHead(304, {
|
||||
'DS-Interceptor': 'cache: ' + maxAge
|
||||
'DS-Interceptor': `cache: ${maxAge}`
|
||||
})
|
||||
res.end()
|
||||
|
||||
|
|
|
@ -3,20 +3,18 @@ const lodash = require('lodash')
|
|||
|
||||
// 替换占位符
|
||||
function replacePlaceholder (url, rOptions, matched) {
|
||||
if (url.indexOf('${') >= 0) {
|
||||
// eslint-disable-next-line
|
||||
// no-template-curly-in-string
|
||||
if (url.includes('${')) {
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
url = url.replace('${host}', rOptions.hostname)
|
||||
|
||||
if (matched && url.indexOf('${') >= 0) {
|
||||
if (matched && url.includes('${')) {
|
||||
for (let i = 0; i < matched.length; i++) {
|
||||
url = url.replace('${m[' + i + ']}', matched[i] == null ? '' : matched[i])
|
||||
url = url.replace(`\${m[${i}]}`, matched[i] == null ? '' : matched[i])
|
||||
}
|
||||
}
|
||||
|
||||
// 移除多余的占位符
|
||||
if (url.indexOf('${') >= 0) {
|
||||
if (url.includes('${')) {
|
||||
url = url.replace(/\$\{[^}]+}/g, '')
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +43,7 @@ function buildTargetUrl (rOptions, urlConf, interceptOpt, matched) {
|
|||
targetUrl = replacePlaceholder(targetUrl, rOptions, matched)
|
||||
|
||||
// 拼接协议
|
||||
targetUrl = targetUrl.indexOf('http:') === 0 || targetUrl.indexOf('https:') === 0 ? targetUrl : rOptions.protocol + '//' + targetUrl
|
||||
targetUrl = targetUrl.indexOf('http:') === 0 || targetUrl.indexOf('https:') === 0 ? targetUrl : `${rOptions.protocol}//${targetUrl}`
|
||||
|
||||
return targetUrl
|
||||
}
|
||||
|
@ -90,7 +88,7 @@ module.exports = {
|
|||
for (const bk of interceptOpt.backup) {
|
||||
backupList.push(bk)
|
||||
}
|
||||
const key = rOptions.hostname + '/' + interceptOpt.key
|
||||
const key = `${rOptions.hostname}/${interceptOpt.key}`
|
||||
const count = RequestCounter.getOrCreate(key, backupList)
|
||||
if (count.value == null) {
|
||||
count.doRank()
|
||||
|
|
|
@ -32,7 +32,7 @@ module.exports = {
|
|||
// 替换请求头
|
||||
if (requestReplaceConfig.headers) {
|
||||
replaceRequestHeaders(rOptions, requestReplaceConfig.headers, log)
|
||||
actions += (actions ? ',' : '') + 'headers'
|
||||
actions += `${actions ? ',' : ''}headers`
|
||||
}
|
||||
|
||||
// 替换下载文件请求的请求地址(此功能主要是为了方便拦截配置)
|
||||
|
@ -40,7 +40,7 @@ module.exports = {
|
|||
if (requestReplaceConfig.doDownload && rOptions.path.match(/DS_DOWNLOAD/i)) {
|
||||
rOptions.doDownload = true
|
||||
rOptions.path = rOptions.path.replace(/[?&/]?DS_DOWNLOAD(=[^?&/]+)?$/gi, '')
|
||||
actions += (actions ? ',' : '') + 'path:remove-DS_DOWNLOAD'
|
||||
actions += `${actions ? ',' : ''}path:remove-DS_DOWNLOAD`
|
||||
}
|
||||
|
||||
res.setHeader('DS-RequestReplace-Interceptor', actions)
|
||||
|
|
|
@ -12,7 +12,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
// 判断当前响应码是否不使用缓存
|
||||
if (interceptOpt.cacheExcludeStatusCodeList && interceptOpt.cacheExcludeStatusCodeList[proxyRes.statusCode + '']) {
|
||||
if (interceptOpt.cacheExcludeStatusCodeList && interceptOpt.cacheExcludeStatusCodeList[`${proxyRes.statusCode}`]) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ module.exports = {
|
|||
// 获取maxAge配置
|
||||
let maxAge = cacheReq.getMaxAge(interceptOpt)
|
||||
// public 或 private
|
||||
const cacheControlType = (interceptOpt.cacheControlType || 'public') + ', '
|
||||
const cacheControlType = `${interceptOpt.cacheControlType || 'public'}, `
|
||||
// immutable属性
|
||||
const cacheImmutable = interceptOpt.cacheImmutable !== false ? ', immutable' : ''
|
||||
|
||||
|
@ -65,7 +65,7 @@ module.exports = {
|
|||
if (originalHeaders.cacheControl) {
|
||||
const maxAgeMatch = originalHeaders.cacheControl.value.match(/max-age=(\d+)/)
|
||||
if (maxAgeMatch && maxAgeMatch[1] > maxAge) {
|
||||
if (interceptOpt.cacheImmutable !== false && originalHeaders.cacheControl.value.indexOf('immutable') < 0) {
|
||||
if (interceptOpt.cacheImmutable !== false && !originalHeaders.cacheControl.value.includes('immutable')) {
|
||||
maxAge = maxAgeMatch[1]
|
||||
} else {
|
||||
const url = `${rOptions.method} ➜ ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${req.url}`
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const lodash = require('lodash')
|
||||
const cacheReq = require('../req/cacheReq')
|
||||
|
||||
const REMOVE = '[remove]'
|
||||
|
||||
// 替换响应头
|
||||
|
@ -96,17 +97,17 @@ module.exports = {
|
|||
replaceHeaders.expires = '[remove]'
|
||||
}
|
||||
|
||||
actions += (actions ? ',' : '') + 'download:' + filename
|
||||
actions += `${actions ? ',' : ''}download:${filename}`
|
||||
}
|
||||
|
||||
// 替换响应头
|
||||
if (replaceResponseHeaders(replaceHeaders, res, proxyRes)) {
|
||||
actions += (actions ? ',' : '') + 'headers'
|
||||
actions += `${actions ? ',' : ''}headers`
|
||||
}
|
||||
|
||||
if (actions) {
|
||||
res.setHeader('DS-ResponseReplace-Interceptor', actions)
|
||||
log.info('response intercept: ' + actions)
|
||||
log.info(`response intercept: ${actions}`)
|
||||
}
|
||||
},
|
||||
is (interceptOpt) {
|
||||
|
|
|
@ -29,7 +29,7 @@ module.exports = {
|
|||
}
|
||||
|
||||
// 如果没有响应头 'content-type',或其值不是 'text/html',则不处理
|
||||
if (!proxyRes.headers['content-type'] || proxyRes.headers['content-type'].indexOf('text/html') < 0) {
|
||||
if (!proxyRes.headers['content-type'] || !proxyRes.headers['content-type'].includes('text/html')) {
|
||||
res.setHeader('DS-Script-Interceptor', 'Not text/html')
|
||||
return
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ module.exports = {
|
|||
|
||||
let scriptTag
|
||||
|
||||
if (key.indexOf('/') >= 0) {
|
||||
if (key.includes('/')) {
|
||||
scriptTag = getScriptByUrlOrPath(key) // 1.绝对地址或相对地址(注意:当目标站点限制跨域脚本时,可使用相对地址,再结合proxy拦截器进行代理,可规避掉限制跨域脚本问题。)
|
||||
} else {
|
||||
const script = scripts[key]
|
||||
|
@ -60,7 +60,7 @@ module.exports = {
|
|||
scriptTag = getScript(key, script.script) // 2.DS内置脚本
|
||||
}
|
||||
|
||||
tags += '\r\n\t' + scriptTag
|
||||
tags += `\r\n\t${scriptTag}`
|
||||
}
|
||||
|
||||
// 如果脚本为空,则不插入
|
||||
|
@ -70,15 +70,15 @@ module.exports = {
|
|||
|
||||
// 插入油猴脚本浏览器扩展
|
||||
if (typeof interceptOpt.tampermonkeyScript === 'string') {
|
||||
tags = '\r\n\t' + getScriptByUrlOrPath(interceptOpt.tampermonkeyScript) + tags
|
||||
tags = `\r\n\t${getScriptByUrlOrPath(interceptOpt.tampermonkeyScript)}${tags}`
|
||||
} else {
|
||||
tags = '\r\n\t' + getScript('tampermonkey', scripts.tampermonkey.script) + tags
|
||||
tags = `\r\n\t${getScript('tampermonkey', scripts.tampermonkey.script)}${tags}`
|
||||
}
|
||||
|
||||
res.setHeader('DS-Script-Interceptor', 'true')
|
||||
log.info(`script response intercept: insert script ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${rOptions.path}`, ', head:', tags)
|
||||
return {
|
||||
head: tags + '\r\n'
|
||||
head: `${tags}\r\n`
|
||||
}
|
||||
} catch (err) {
|
||||
try {
|
||||
|
@ -102,10 +102,12 @@ module.exports = {
|
|||
const handleScriptUrl = (scriptUrl, name, replaceScriptUrlFun) => {
|
||||
if (scriptUrl.indexOf('https:') === 0 || scriptUrl.indexOf('http:') === 0) {
|
||||
// 绝对地址
|
||||
const scriptKey = SCRIPT_PROXY_URL_PRE + scriptUrl.replace('.js', '').replace(/[\W_]+/g, '_') + '.js' // 伪脚本地址:移除 script 中可能存在的特殊字符,并转为相对地址
|
||||
const scriptKey = `${SCRIPT_PROXY_URL_PRE + scriptUrl.replace('.js', '').replace(/[\W_]+/g, '_')}.js` // 伪脚本地址:移除 script 中可能存在的特殊字符,并转为相对地址
|
||||
scriptProxy[scriptKey] = scriptUrl
|
||||
log.info(`替换${name}配置值:'${scriptUrl}' -> '${scriptKey}'`)
|
||||
if (typeof replaceScriptUrlFun === 'function') replaceScriptUrlFun(scriptKey)
|
||||
if (typeof replaceScriptUrlFun === 'function') {
|
||||
replaceScriptUrlFun(scriptKey)
|
||||
}
|
||||
} else if (scriptUrl.indexOf('/') === 0) {
|
||||
// 相对地址
|
||||
scriptProxy[scriptUrl] = scriptUrl
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const log = require('../../utils/util.log')
|
||||
|
||||
let scripts
|
||||
|
||||
function buildScript (sc, content, scriptName) {
|
||||
const scriptKey = `ds_${scriptName}${sc.version ? ('_' + sc.version) : ''}:`
|
||||
const scriptKey = `ds_${scriptName}${sc.version ? (`_${sc.version}`) : ''}:`
|
||||
|
||||
// 代码1:监听事件
|
||||
const runAt = sc['run-at'] || 'document-end'
|
||||
|
@ -45,9 +46,9 @@ if (!((window.__ds_global__ || {}).GM_getValue || (() => true))("ds_enabled", tr
|
|||
}
|
||||
|
||||
if (item.indexOf('.') > 0) {
|
||||
grantStr += item + ' = (window.__ds_global__ || {})[\'' + item + '\'];'
|
||||
grantStr += `${item} = (window.__ds_global__ || {})['${item}'];`
|
||||
} else {
|
||||
grantStr += 'const ' + item + ' = (window.__ds_global__ || {})[\'' + item + '\'] || (() => {});'
|
||||
grantStr += `const ${item} = (window.__ds_global__ || {})['${item}'] || (() => {});`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +82,7 @@ function loadScript (content, scriptName) {
|
|||
script: ''
|
||||
}
|
||||
for (const string of confItemArr) {
|
||||
const reg = new RegExp('.*@([^\\s]+)\\s(.+)')
|
||||
const reg = new RegExp('.*@(\\S+)\\s(.+)')
|
||||
const ret = string.match(reg)
|
||||
if (ret) {
|
||||
const key = ret[1].trim()
|
||||
|
@ -103,7 +104,7 @@ function loadScript (content, scriptName) {
|
|||
|
||||
function readFile (rootDir, script) {
|
||||
log.info('read script, script root location:', path.resolve('./'))
|
||||
const location = path.join(rootDir, './' + script)
|
||||
const location = path.join(rootDir, `./${script}`)
|
||||
log.info('read script, the script location:', location)
|
||||
return fs.readFileSync(location).toString()
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const path = require('path')
|
||||
|
||||
const config = exports
|
||||
|
||||
config.defaultHost = '127.0.0.1'
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
const url = require('url')
|
||||
const Agent = require('./ProxyHttpAgent')
|
||||
const HttpsAgent = require('./ProxyHttpsAgent')
|
||||
const tunnelAgent = require('tunnel-agent')
|
||||
const log = require('../../../utils/util.log')
|
||||
const matchUtil = require('../../../utils/util.match')
|
||||
const Agent = require('./ProxyHttpAgent')
|
||||
const HttpsAgent = require('./ProxyHttpsAgent')
|
||||
|
||||
const util = exports
|
||||
|
||||
const httpsAgentCache = {}
|
||||
|
@ -25,7 +26,7 @@ function getTimeoutConfig (hostname, serverSetting) {
|
|||
}
|
||||
|
||||
function createHttpsAgent (timeoutConfig, verifySsl) {
|
||||
const key = timeoutConfig.timeout + '-' + timeoutConfig.keepAliveTimeout
|
||||
const key = `${timeoutConfig.timeout}-${timeoutConfig.keepAliveTimeout}`
|
||||
if (!httpsAgentCache[key]) {
|
||||
verifySsl = !!verifySsl
|
||||
|
||||
|
@ -57,7 +58,7 @@ function createHttpsAgent (timeoutConfig, verifySsl) {
|
|||
}
|
||||
|
||||
function createHttpAgent (timeoutConfig) {
|
||||
const key = timeoutConfig.timeout + '-' + timeoutConfig.keepAliveTimeout
|
||||
const key = `${timeoutConfig.timeout}-${timeoutConfig.keepAliveTimeout}`
|
||||
if (!httpAgentCache[key]) {
|
||||
httpAgentCache[key] = new Agent({
|
||||
keepAlive: true,
|
||||
|
@ -80,12 +81,12 @@ util.parseHostnameAndPort = (host, defaultPort) => {
|
|||
if (arr) {
|
||||
arr = arr.slice(1)
|
||||
if (arr[1]) {
|
||||
arr[1] = parseInt(arr[1], 10)
|
||||
arr[1] = Number.parseInt(arr[1], 10)
|
||||
}
|
||||
} else {
|
||||
arr = host.split(':')
|
||||
if (arr.length > 1) {
|
||||
arr[1] = parseInt(arr[1], 10)
|
||||
arr[1] = Number.parseInt(arr[1], 10)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,7 +189,7 @@ util.getTunnelAgent = (requestIsSSL, externalProxyUrl) => {
|
|||
httpsOverHttpAgent = tunnelAgent.httpsOverHttp({
|
||||
proxy: {
|
||||
host: hostname,
|
||||
port: port
|
||||
port
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -198,7 +199,7 @@ util.getTunnelAgent = (requestIsSSL, externalProxyUrl) => {
|
|||
httpsOverHttpsAgent = tunnelAgent.httpsOverHttps({
|
||||
proxy: {
|
||||
host: hostname,
|
||||
port: port
|
||||
port
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -220,7 +221,7 @@ util.getTunnelAgent = (requestIsSSL, externalProxyUrl) => {
|
|||
httpOverHttpsAgent = tunnelAgent.httpOverHttps({
|
||||
proxy: {
|
||||
host: hostname,
|
||||
port: port
|
||||
port
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const log = require('../../../utils/util.log')
|
||||
const through = require('through2')
|
||||
const zlib = require('zlib')
|
||||
const through = require('through2')
|
||||
const log = require('../../../utils/util.log')
|
||||
|
||||
// 编解码器
|
||||
const codecMap = {
|
||||
|
@ -84,7 +84,7 @@ function injectScriptIntoHtml (tags, chunk, script) {
|
|||
}
|
||||
|
||||
function handleResponseHeaders (res, proxyRes) {
|
||||
Object.keys(proxyRes.headers).forEach(function (key) {
|
||||
Object.keys(proxyRes.headers).forEach((key) => {
|
||||
if (proxyRes.headers[key] !== undefined) {
|
||||
// let newkey = key.replace(/^[a-z]|-[a-z]/g, (match) => {
|
||||
// return match.toUpperCase()
|
||||
|
@ -100,7 +100,7 @@ function handleResponseHeaders (res, proxyRes) {
|
|||
const reg = /script-src ([^:]*);/i
|
||||
const matched = policy.match(reg)
|
||||
if (matched) {
|
||||
if (matched[1].indexOf('self') < 0) {
|
||||
if (!matched[1].includes('self')) {
|
||||
policy = policy.replace('script-src', 'script-src \'self\' ')
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ function handleResponseHeaders (res, proxyRes) {
|
|||
|
||||
const contextPath = '/____ds_script____/'
|
||||
const monkey = require('../../monkey')
|
||||
|
||||
module.exports = {
|
||||
requestIntercept (context, req, res, ssl, next) {
|
||||
const { rOptions, log, setting } = context
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
const url = require('url')
|
||||
const request = require('request')
|
||||
const lodash = require('lodash')
|
||||
const pac = require('./source/pac')
|
||||
const matchUtil = require('../../../utils/util.match')
|
||||
const log = require('../../../utils/util.log')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const { Buffer } = require('buffer')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const url = require('url')
|
||||
const lodash = require('lodash')
|
||||
const request = require('request')
|
||||
const log = require('../../../utils/util.log')
|
||||
const matchUtil = require('../../../utils/util.match')
|
||||
const pac = require('./source/pac')
|
||||
|
||||
let pacClient = null
|
||||
|
||||
function matched (hostname, overWallTargetMap) {
|
||||
|
@ -23,7 +24,7 @@ function matched (hostname, overWallTargetMap) {
|
|||
if (pacClient == null) {
|
||||
return null
|
||||
}
|
||||
const ret = pacClient.FindProxyForURL('https://' + hostname, hostname)
|
||||
const ret = pacClient.FindProxyForURL(`https://${hostname}`, hostname)
|
||||
if (ret && ret.indexOf('PROXY ') === 0) {
|
||||
log.info(`matchHostname: matched overwall: '${hostname}' -> '${ret}' in pac.txt`)
|
||||
return 'in pac.txt'
|
||||
|
@ -113,12 +114,12 @@ async function downloadPacAsync (pacConfig) {
|
|||
// 尝试解析Base64(注:https://gitlab.com/gfwlist/gfwlist/raw/master/gfwlist.txt 下载下来的是Base64格式)
|
||||
let pacTxt = body
|
||||
try {
|
||||
if (pacTxt.indexOf('!---------------------EOF') < 0) {
|
||||
if (!pacTxt.includes('!---------------------EOF')) {
|
||||
pacTxt = Buffer.from(pacTxt, 'base64').toString('utf8')
|
||||
// log.debug('解析 base64 后的 pax:', pacTxt)
|
||||
}
|
||||
} catch (e) {
|
||||
if (pacTxt.indexOf('!---------------------EOF') < 0) {
|
||||
if (!pacTxt.includes('!---------------------EOF')) {
|
||||
log.error(`远程 pac.txt 文件内容即不是base64格式,也不是要求的格式,url: ${remotePacFileUrl},body: ${body}`)
|
||||
return
|
||||
}
|
||||
|
@ -190,10 +191,10 @@ function createOverwallMiddleware (overWallConfig) {
|
|||
const port = server[domain].port
|
||||
const path = server[domain].path
|
||||
const password = server[domain].password
|
||||
const proxyTarget = domain + '/' + path + '/' + hostname + req.url
|
||||
const proxyTarget = `${domain}/${path}/${hostname}${req.url}`
|
||||
|
||||
// const backup = interceptOpt.backup
|
||||
const proxy = proxyTarget.indexOf('http:') === 0 || proxyTarget.indexOf('https:') === 0 ? proxyTarget : (rOptions.protocol + '//' + proxyTarget)
|
||||
const proxy = proxyTarget.indexOf('http:') === 0 || proxyTarget.indexOf('https:') === 0 ? proxyTarget : (`${rOptions.protocol}//${proxyTarget}`)
|
||||
// eslint-disable-next-line node/no-deprecated-api
|
||||
const URL = url.parse(proxy)
|
||||
rOptions.origional = lodash.cloneDeep(rOptions) // 备份原始请求参数
|
||||
|
|
|
@ -20,7 +20,7 @@ function createPacClient (pacFilePath) {
|
|||
|
||||
const getRules = function (pacFilePath) {
|
||||
let text = readFile(pacFilePath)
|
||||
if (text.indexOf('!---------------------EOF') < 0) {
|
||||
if (!text.includes('!---------------------EOF')) {
|
||||
text = Buffer.from(text, 'base64').toString()
|
||||
}
|
||||
const rules = []
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
const net = require('net')
|
||||
const url = require('url')
|
||||
const jsonApi = require('../../../json')
|
||||
const log = require('../../../utils/util.log')
|
||||
const DnsUtil = require('../../dns/index')
|
||||
const localIP = '127.0.0.1'
|
||||
const dnsLookup = require('./dnsLookup')
|
||||
const jsonApi = require('../../../json')
|
||||
|
||||
const localIP = '127.0.0.1'
|
||||
|
||||
function isSslConnect (sslConnectInterceptors, req, cltSocket, head) {
|
||||
for (const intercept of sslConnectInterceptors) {
|
||||
|
@ -32,7 +33,7 @@ module.exports = function createConnectHandler (sslConnectInterceptor, middlewar
|
|||
return function connectHandler (req, cltSocket, head, ssl) {
|
||||
// eslint-disable-next-line node/no-deprecated-api
|
||||
let { hostname, port } = url.parse(`${ssl ? 'https' : 'http'}://${req.url}`)
|
||||
port = parseInt(port)
|
||||
port = Number.parseInt(port)
|
||||
|
||||
if (isSslConnect(sslConnectInterceptors, req, cltSocket, head)) {
|
||||
// 需要拦截,代替目标服务器,让客户端连接DS在本地启动的代理服务
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const fs = require('fs')
|
||||
const forge = require('node-forge')
|
||||
const FakeServersCenter = require('../tls/FakeServersCenter')
|
||||
const log = require('../../../utils/util.log')
|
||||
const FakeServersCenter = require('../tls/FakeServersCenter')
|
||||
|
||||
module.exports = function createFakeServerCenter ({
|
||||
maxLength,
|
||||
caCertPath,
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
const http = require('http')
|
||||
const https = require('https')
|
||||
const commonUtil = require('../common/util')
|
||||
const jsonApi = require('../../../json')
|
||||
// const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i
|
||||
const DnsUtil = require('../../dns/index')
|
||||
const log = require('../../../utils/util.log')
|
||||
const RequestCounter = require('../../choice/RequestCounter')
|
||||
const commonUtil = require('../common/util')
|
||||
// const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i
|
||||
const DnsUtil = require('../../dns/index')
|
||||
const compatible = require('../compatible/compatible')
|
||||
const InsertScriptMiddleware = require('../middleware/InsertScriptMiddleware')
|
||||
const dnsLookup = require('./dnsLookup')
|
||||
const compatible = require('../compatible/compatible')
|
||||
|
||||
const MAX_SLOW_TIME = 8000 // 超过此时间 则认为太慢了
|
||||
|
||||
// create requestHandler function
|
||||
|
@ -63,7 +64,9 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
}
|
||||
const goNext = reqIncpt.requestIntercept(context, req, res, ssl, next)
|
||||
if (goNext) {
|
||||
if (goNext !== 'no-next') next()
|
||||
if (goNext !== 'no-next') {
|
||||
next()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +110,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
function onFree () {
|
||||
url = `${rOptions.method} ➜ ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${rOptions.path}`
|
||||
const start = new Date()
|
||||
log.info('发起代理请求:', url, (rOptions.servername ? ', sni: ' + rOptions.servername : ''), ', headers:', jsonApi.stringify2(rOptions.headers))
|
||||
log.info('发起代理请求:', url, (rOptions.servername ? `, sni: ${rOptions.servername}` : ''), ', headers:', jsonApi.stringify2(rOptions.headers))
|
||||
|
||||
const isDnsIntercept = {}
|
||||
if (dnsConfig && dnsConfig.dnsMap) {
|
||||
|
@ -181,7 +184,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
proxyReq.on('error', (e) => {
|
||||
const cost = new Date() - start
|
||||
log.error(`代理请求错误: ${url}, cost: ${cost} ms, error:`, e, ', rOptions:', jsonApi.stringify2(rOptions))
|
||||
countSlow(isDnsIntercept, '代理请求错误: ' + e.message)
|
||||
countSlow(isDnsIntercept, `代理请求错误: ${e.message}`)
|
||||
reject(e)
|
||||
|
||||
// 自动兼容程序:2
|
||||
|
@ -205,7 +208,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
})
|
||||
|
||||
// 原始请求的事件监听
|
||||
req.on('aborted', function () {
|
||||
req.on('aborted', () => {
|
||||
const cost = new Date() - start
|
||||
const errorMsg = `请求被取消: ${url}, cost: ${cost} ms`
|
||||
log.error(errorMsg, ', rOptions:', jsonApi.stringify2(rOptions))
|
||||
|
@ -215,7 +218,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
}
|
||||
reject(new Error(errorMsg))
|
||||
})
|
||||
req.on('error', function (e, req, res) {
|
||||
req.on('error', (e, req, res) => {
|
||||
const cost = new Date() - start
|
||||
log.error(`请求错误: ${url}, cost: ${cost} ms, error:`, e, ', rOptions:', jsonApi.stringify2(rOptions))
|
||||
reject(e)
|
||||
|
@ -246,7 +249,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
// // console.log('BODY: ')
|
||||
// })
|
||||
proxyRes.on('error', (error) => {
|
||||
countSlow(null, 'error: ' + error.message)
|
||||
countSlow(null, `error: ${error.message}`)
|
||||
log.error(`proxy res error: ${url}, error:`, error)
|
||||
})
|
||||
|
||||
|
@ -300,7 +303,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
await responseInterceptorPromise
|
||||
|
||||
if (!res.headersSent) { // prevent duplicate set headers
|
||||
Object.keys(proxyRes.headers).forEach(function (key) {
|
||||
Object.keys(proxyRes.headers).forEach((key) => {
|
||||
if (proxyRes.headers[key] !== undefined) {
|
||||
// https://github.com/nodejitsu/node-http-proxy/issues/362
|
||||
if (/^www-authenticate$/i.test(key)) {
|
||||
|
@ -314,12 +317,12 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
})
|
||||
|
||||
if (proxyRes.statusCode >= 400) {
|
||||
countSlow(null, 'Status return: ' + proxyRes.statusCode)
|
||||
countSlow(null, `Status return: ${proxyRes.statusCode}`)
|
||||
}
|
||||
res.writeHead(proxyRes.statusCode)
|
||||
proxyRes.pipe(res)
|
||||
}
|
||||
})().catch(e => {
|
||||
})().catch((e) => {
|
||||
if (!res.writableEnded) {
|
||||
try {
|
||||
const status = e.status || 500
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const http = require('http')
|
||||
const https = require('https')
|
||||
const util = require('../common/util')
|
||||
const log = require('../../../utils/util.log')
|
||||
const util = require('../common/util')
|
||||
|
||||
// copy from node-http-proxy. ^_^
|
||||
|
||||
// create connectHandler function
|
||||
|
@ -13,17 +14,19 @@ module.exports = function createUpgradeHandler (serverSetting) {
|
|||
proxyReq.on('error', (e) => {
|
||||
log.error('upgradeHandler error:', e)
|
||||
})
|
||||
proxyReq.on('response', function (res) {
|
||||
proxyReq.on('response', (res) => {
|
||||
// if upgrade event isn't going to happen, close the socket
|
||||
if (!res.upgrade) cltSocket.end()
|
||||
if (!res.upgrade) {
|
||||
cltSocket.end()
|
||||
}
|
||||
})
|
||||
|
||||
proxyReq.on('upgrade', function (proxyRes, proxySocket, proxyHead) {
|
||||
proxyReq.on('upgrade', (proxyRes, proxySocket, proxyHead) => {
|
||||
proxySocket.on('error', (e) => {
|
||||
log.error('upgrade error:', e)
|
||||
})
|
||||
|
||||
cltSocket.on('error', function (e) {
|
||||
cltSocket.on('error', (e) => {
|
||||
log.error('upgrade socket error:', e)
|
||||
proxySocket.end()
|
||||
})
|
||||
|
@ -33,23 +36,24 @@ module.exports = function createUpgradeHandler (serverSetting) {
|
|||
|
||||
proxySocket.setKeepAlive(true, 0)
|
||||
|
||||
if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead)
|
||||
if (proxyHead && proxyHead.length) {
|
||||
proxySocket.unshift(proxyHead)
|
||||
}
|
||||
|
||||
cltSocket.write(
|
||||
Object.keys(proxyRes.headers).reduce(function (head, key) {
|
||||
`${Object.keys(proxyRes.headers).reduce((head, key) => {
|
||||
const value = proxyRes.headers[key]
|
||||
|
||||
if (!Array.isArray(value)) {
|
||||
head.push(key + ': ' + value)
|
||||
head.push(`${key}: ${value}`)
|
||||
return head
|
||||
}
|
||||
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
head.push(key + ': ' + value[i])
|
||||
head.push(`${key}: ${value[i]}`)
|
||||
}
|
||||
return head
|
||||
}, ['HTTP/1.1 101 Switching Protocols'])
|
||||
.join('\r\n') + '\r\n\r\n'
|
||||
}, ['HTTP/1.1 101 Switching Protocols']).join('\r\n')}\r\n\r\n`
|
||||
)
|
||||
|
||||
proxySocket.pipe(cltSocket).pipe(proxySocket)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const speedTest = require('../../speed')
|
||||
const log = require('../../../utils/util.log')
|
||||
const defaultDns = require('dns')
|
||||
const log = require('../../../utils/util.log')
|
||||
const speedTest = require('../../speed')
|
||||
|
||||
module.exports = {
|
||||
createLookupFunc: function (res, dns, action, target, isDnsIntercept) {
|
||||
target = target ? (', target: ' + target) : ''
|
||||
createLookupFunc (res, dns, action, target, isDnsIntercept) {
|
||||
target = target ? (`, target: ${target}`) : ''
|
||||
|
||||
return (hostname, options, callback) => {
|
||||
const tester = speedTest.getSpeedTester(hostname)
|
||||
|
@ -12,14 +12,16 @@ module.exports = {
|
|||
const aliveIpObj = tester.pickFastAliveIpObj()
|
||||
if (aliveIpObj) {
|
||||
log.info(`----- ${action}: ${hostname}, use alive ip from dns '${aliveIpObj.dns}': ${aliveIpObj.host}${target} -----`)
|
||||
if (res) res.setHeader('DS-DNS-Lookup', `IpTester: ${aliveIpObj.host} ${aliveIpObj.dns === '预设IP' ? 'PreSet' : aliveIpObj.dns}`)
|
||||
if (res) {
|
||||
res.setHeader('DS-DNS-Lookup', `IpTester: ${aliveIpObj.host} ${aliveIpObj.dns === '预设IP' ? 'PreSet' : aliveIpObj.dns}`)
|
||||
}
|
||||
callback(null, aliveIpObj.host, 4)
|
||||
return
|
||||
} else {
|
||||
log.info(`----- ${action}: ${hostname}, no alive ip${target}, tester: { "ready": ${tester.ready}, "backupList": ${JSON.stringify(tester.backupList)} }`)
|
||||
}
|
||||
}
|
||||
dns.lookup(hostname).then(ip => {
|
||||
dns.lookup(hostname).then((ip) => {
|
||||
if (isDnsIntercept) {
|
||||
isDnsIntercept.dns = dns
|
||||
isDnsIntercept.hostname = hostname
|
||||
|
@ -42,7 +44,9 @@ module.exports = {
|
|||
}
|
||||
if (isTestFailedIp === false) {
|
||||
log.info(`----- ${action}: ${hostname}, use ip from dns '${dns.name}': ${ip}${target} -----`)
|
||||
if (res) res.setHeader('DS-DNS-Lookup', `DNS: ${ip} ${dns.name === '预设IP' ? 'PreSet' : dns.name}`)
|
||||
if (res) {
|
||||
res.setHeader('DS-DNS-Lookup', `DNS: ${ip} ${dns.name === '预设IP' ? 'PreSet' : dns.name}`)
|
||||
}
|
||||
callback(null, ip, 4)
|
||||
return
|
||||
} else {
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
const tlsUtils = require('../tls/tlsUtils')
|
||||
const http = require('http')
|
||||
const config = require('../common/config')
|
||||
const log = require('../../../utils/util.log')
|
||||
const createRequestHandler = require('./createRequestHandler')
|
||||
const speedTest = require('../../speed/index.js')
|
||||
const config = require('../common/config')
|
||||
const tlsUtils = require('../tls/tlsUtils')
|
||||
const createConnectHandler = require('./createConnectHandler')
|
||||
const createFakeServerCenter = require('./createFakeServerCenter')
|
||||
const createRequestHandler = require('./createRequestHandler')
|
||||
const createUpgradeHandler = require('./createUpgradeHandler')
|
||||
const speedTest = require('../../speed/index.js')
|
||||
|
||||
module.exports = {
|
||||
createProxy ({
|
||||
host = config.defaultHost,
|
||||
|
@ -96,7 +97,7 @@ module.exports = {
|
|||
connectHandler(req, cltSocket, head, ssl)
|
||||
})
|
||||
// TODO: handler WebSocket
|
||||
server.on('upgrade', function (req, cltSocket, head) {
|
||||
server.on('upgrade', (req, cltSocket, head) => {
|
||||
if (printDebugLog) {
|
||||
log.debug(`【server upgrade, ssl: ${ssl}】\r\n----- req -----\r\n`, req)
|
||||
} else {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
const https = require('https')
|
||||
const http = require('http')
|
||||
const tlsUtils = require('./tlsUtils')
|
||||
const CertAndKeyContainer = require('./CertAndKeyContainer')
|
||||
const https = require('https')
|
||||
const forge = require('node-forge')
|
||||
const CertAndKeyContainer = require('./CertAndKeyContainer')
|
||||
const tlsUtils = require('./tlsUtils')
|
||||
|
||||
const pki = forge.pki
|
||||
// const colors = require('colors')
|
||||
const tls = require('tls')
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue