Merge remote-tracking branch 'origin/master'

# Conflicts:
#	packages/core/src/utils/util.log.js
#	packages/gui/src/utils/util.log.js
#	packages/mitmproxy/src/utils/util.log.js
pull/67/head
xiaojunnuo 2020-11-30 22:01:54 +08:00
commit 78116101a0
38 changed files with 389 additions and 211 deletions

View File

@ -50,7 +50,7 @@
#### 1 下载安装包 #### 1 下载安装包
下载安装包: 下载安装包:
[阿里云](https://dev-sidecar.docmirror.cn/update/DevSidecar-1.2.1.exe) [阿里云](https://dev-sidecar.docmirror.cn/update/DevSidecar-1.2.2.exe)
[Gitee Release](https://gitee.com/docmirror/dev-sidecar/releases) [Gitee Release](https://gitee.com/docmirror/dev-sidecar/releases)
[Github Release](https://github.com/docmirror/dev-sidecar/releases) [Github Release](https://github.com/docmirror/dev-sidecar/releases)

View File

@ -14,5 +14,5 @@
"ignore": [] "ignore": []
} }
}, },
"version": "1.2.1" "version": "1.2.2"
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@docmirror/dev-sidecar", "name": "@docmirror/dev-sidecar",
"version": "1.2.1", "version": "1.2.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "@docmirror/dev-sidecar", "name": "@docmirror/dev-sidecar",
"version": "1.2.1", "version": "1.2.2",
"description": "给开发者的加速代理工具", "description": "给开发者的加速代理工具",
"main": "src/index.js", "main": "src/index.js",
"keywords": [ "keywords": [
@ -16,7 +16,7 @@
"start": "node ./start" "start": "node ./start"
}, },
"dependencies": { "dependencies": {
"@docmirror/mitmproxy": "^1.2.1", "@docmirror/mitmproxy": "^1.2.2",
"agentkeepalive": "^2.1.1", "agentkeepalive": "^2.1.1",
"charset": "^1.0.0", "charset": "^1.0.0",
"child_process": "^1.0.2", "child_process": "^1.0.2",

View File

@ -49,11 +49,11 @@ module.exports = {
desc: 'clone加速复制链接脚本' desc: 'clone加速复制链接脚本'
}, },
'/.*': { '/.*': {
proxy: 'github.com', proxy: 'gh.docmirror.top/_proxy',
backup: [ backup: [
'gh.docmirror.top/_proxy' 'github.com'
], ],
desc: '如果出现dev-sidecar报错可能是备用加速地址dns被污染了需要将本条配置删除' desc: '如果出现dev-sidecar报错可能是加速地址dns被污染了需要将本条配置删除'
} }
}, },
'api.github.com': { 'api.github.com': {
@ -77,6 +77,13 @@ module.exports = {
'.*': { proxy: 'customer-stories-feed.fastgit.org' } '.*': { proxy: 'customer-stories-feed.fastgit.org' }
}, },
// google cdn // google cdn
'www.google.com': {
'/recaptcha/.*': { proxy: 'www.recaptcha.net' },
'.*': {
proxy: 'gg.docmirror.top/_yxorp',
desc: '呀,被你发现了,偷偷的用,别声张'
}
},
'ajax.googleapis.com': { 'ajax.googleapis.com': {
'.*': { '.*': {
proxy: 'ajax.loli.net', proxy: 'ajax.loli.net',
@ -99,9 +106,6 @@ module.exports = {
'themes.googleusercontent.com': { 'themes.googleusercontent.com': {
'.*': { proxy: 'google-themes.proxy.ustclug.org' } '.*': { proxy: 'google-themes.proxy.ustclug.org' }
}, },
'www.google.com': {
'/recaptcha/.*': { proxy: 'www.recaptcha.net' }
},
'fonts.gstatic.com': { 'fonts.gstatic.com': {
'.*': { '.*': {
proxy: 'gstatic.loli.net', proxy: 'gstatic.loli.net',

View File

@ -3,11 +3,12 @@
*/ */
const Shell = require('../../shell') const Shell = require('../../shell')
const execute = Shell.execute const execute = Shell.execute
const execFile = Shell.execFile
const Registry = require('winreg') const Registry = require('winreg')
// const cmd = require('node-cmd')
const refreshInternetPs = require('./refresh-internet') const refreshInternetPs = require('./refresh-internet')
const PowerShell = require('node-powershell') const PowerShell = require('node-powershell')
const log = require('../../../utils/util.log') const log = require('../../../utils/util.log')
const path = require('path')
const _lanIP = [ const _lanIP = [
'localhost', 'localhost',
'127.*', '127.*',
@ -33,6 +34,12 @@ const _lanIP = [
] ]
async function _winUnsetProxy (exec) { async function _winUnsetProxy (exec) {
// eslint-disable-next-line no-constant-condition
if (true) {
const proxyPath = getProxyExePath()
await execFile(proxyPath, ['set', '1'])
return
}
const regKey = new Registry({ const regKey = new Registry({
hive: Registry.HKCU, hive: Registry.HKCU,
key: '\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings' key: '\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings'
@ -48,16 +55,31 @@ async function _winUnsetProxy (exec) {
return true return true
} }
function getProxyExePath () {
const proxyPath = process.env.DS_SYSPROXY_PATH
log.info('proxyPath', proxyPath)
if (proxyPath) {
return proxyPath
}
return path.join(__dirname, './sysproxy.exe')
}
async function _winSetProxy (exec, ip, port) { async function _winSetProxy (exec, ip, port) {
let lanIpStr = ''
for (const string of _lanIP) {
lanIpStr += string + ';'
}
// eslint-disable-next-line no-constant-condition
if (true) {
const proxyPath = getProxyExePath()
await execFile(proxyPath, ['global', `${ip}:${port}`, lanIpStr])
return
}
const regKey = new Registry({ const regKey = new Registry({
hive: Registry.HKCU, hive: Registry.HKCU,
key: '\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings' key: '\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings'
}) })
let lanIpStr = ''
for (const string of _lanIP) {
lanIpStr += string + ';'
}
// log.info('lanIps:', lanIpStr, ip, port) // log.info('lanIps:', lanIpStr, ip, port)
await Promise.all([ await Promise.all([
_winAsyncRegSet(regKey, 'MigrateProxy', Registry.REG_DWORD, 1), _winAsyncRegSet(regKey, 'MigrateProxy', Registry.REG_DWORD, 1),

View File

@ -2,6 +2,7 @@ const util = require('util')
const os = require('os') const os = require('os')
const childProcess = require('child_process') const childProcess = require('child_process')
const _exec = childProcess.exec const _exec = childProcess.exec
const _execFile = childProcess.execFile
const exec = util.promisify(_exec) const exec = util.promisify(_exec)
const PowerShell = require('node-powershell') const PowerShell = require('node-powershell')
const log = require('../utils/util.log') const log = require('../utils/util.log')
@ -119,8 +120,23 @@ async function execute (executor, args) {
return executor[getSystemPlatform()](getSystemShell().exec, args) return executor[getSystemPlatform()](getSystemShell().exec, args)
} }
async function execFile (file, args, options) {
return new Promise((resolve, reject) => {
_execFile(file, args, options, (err, stdout) => {
if (err) {
log.error('文件执行出错:', file, err)
reject(err)
return
}
log.debug('执行成功:', stdout)
resolve(stdout)
})
})
}
module.exports = { module.exports = {
getSystemShell, getSystemShell,
getSystemPlatform, getSystemPlatform,
execute execute,
execFile
} }

View File

@ -3,11 +3,12 @@ const config = require('../config/index')
function getDefaultConfigBasePath () { function getDefaultConfigBasePath () {
return config.server.setting.userBasePath return config.server.setting.userBasePath
} }
const level = process.env.NODE_ENV === 'development' ? 'debug' : 'info'
const path = require('path') const path = require('path')
const filename = path.join(getDefaultConfigBasePath(), '/logs/core.log') const filename = path.join(getDefaultConfigBasePath(), '/logs/core.log')
log4js.configure({ log4js.configure({
appenders: { std: { type: 'stdout' }, file: { type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename } }, appenders: { std: { type: 'stdout' }, file: { type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename} },
categories: { default: { appenders: ['file', 'std'], level: 'info' } } categories: { default: { appenders: ['file', 'std'], level: level } }
}) })
const logger = log4js.getLogger('server') const logger = log4js.getLogger('server')
module.exports = logger module.exports = logger

View File

@ -0,0 +1,20 @@
// ==UserScript==
// @name google增强
// @version 1.2.4
// @author Greper
// @description 去除ping链接
// @match https://www.google.com/*/*
// @icon https://www.google.com/favicon.ico
// @license GPL-3.0 License
// @run-at document-end
// @namespace
// ==/UserScript==
(function () {
console.log('google script loaded')
const aList = document.getElementsByTagName('a')
for (let i = 0; i <= aList.length; i++) {
console.log(aList[i].href)
aList[i].ping = undefined
}
})()

Binary file not shown.

View File

@ -1,6 +1,6 @@
{ {
"name": "@docmirror/dev-sidecar-gui", "name": "@docmirror/dev-sidecar-gui",
"version": "1.2.1", "version": "1.2.2",
"private": false, "private": false,
"license": "MPL-2.0", "license": "MPL-2.0",
"scripts": { "scripts": {
@ -12,10 +12,11 @@
"postuninstall": "electron-builder install-app-deps", "postuninstall": "electron-builder install-app-deps",
"electron:generate-icons": "electron-icon-builder --input=./public/icon.png --output=build --flatten" "electron:generate-icons": "electron-icon-builder --input=./public/icon.png --output=build --flatten"
}, },
"author": "docmirror.cn",
"main": "background.js", "main": "background.js",
"dependencies": { "dependencies": {
"@docmirror/dev-sidecar": "^1.2.1", "@docmirror/dev-sidecar": "^1.2.2",
"@docmirror/mitmproxy": "^1.2.1", "@docmirror/mitmproxy": "^1.2.2",
"ant-design-vue": "^1.6.5", "ant-design-vue": "^1.6.5",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"electron-baidu-tongji": "^1.0.5", "electron-baidu-tongji": "^1.0.5",

View File

@ -1,11 +1,10 @@
'use strict' 'use strict'
/* global __static */ /* global __static */
import path from 'path' import path from 'path'
import { app, protocol, BrowserWindow, Menu, Tray, ipcMain } from 'electron' import { app, protocol, BrowserWindow, Menu, Tray, ipcMain, dialog } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import bridge from './bridge/index' import backend from './bridge/backend'
import updateHandle from './bridge/update-handle' import DevSidecar from '@docmirror/dev-sidecar'
import { ebtMain } from './tongji'
import log from './utils/util.log' import log from './utils/util.log'
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const isMac = process.platform === 'darwin' const isMac = process.platform === 'darwin'
@ -113,7 +112,7 @@ function createWindow () {
} }
async function beforeQuit () { async function beforeQuit () {
return bridge.devSidecar.api.shutdown() return DevSidecar.api.shutdown()
} }
async function quit (app, callback) { async function quit (app, callback) {
if (tray) { if (tray) {
@ -136,12 +135,6 @@ if (!isFirstInstance) {
} else { } else {
app.on('before-quit', async (event) => { app.on('before-quit', async (event) => {
log.info('before-quit') log.info('before-quit')
// event.preventDefault()
// // if (tray) {
// // tray.displayBalloon({ title: '正在关闭,请稍候...', content: '正在关闭中,请稍候。。。' })
// // }
// await bridge.devSidecar.api.shutdown()
// app.exit()
}) })
app.on('second-instance', (event, commandLine, workingDirectory) => { app.on('second-instance', (event, commandLine, workingDirectory) => {
log.info('new app started', commandLine) log.info('new app started', commandLine)
@ -180,24 +173,13 @@ if (!isFirstInstance) {
// log.error('Vue Devtools failed to install:', e.toString()) // log.error('Vue Devtools failed to install:', e.toString())
// } // }
} }
createWindow() try {
bridge.init(win) createWindow()
const context = { win, app, beforeQuit, ipcMain, dialog,log }
let updateUrl = 'https://dev-sidecar.docmirror.cn/update/' backend.install(context) // 模块安装
if (process.env.NODE_ENV === 'development') { } catch (err) {
Object.defineProperty(app, 'isPackaged', { log.info('err', err)
get () {
return true
}
})
updateUrl = 'https://dev-sidecar.docmirror.cn/update/'
// updateUrl = 'http://localhost/dev-sidecar/'
} }
// 自动更新
updateHandle(app, win, beforeQuit, updateUrl)
// 百度分析
ebtMain(ipcMain, isDevelopment)
try { try {
// 最小化到托盘 // 最小化到托盘

View File

@ -1,12 +1,13 @@
import lodash from 'lodash' import lodash from 'lodash'
import DevSidecar from '@docmirror/dev-sidecar' import DevSidecar from '@docmirror/dev-sidecar'
import { ipcMain, Menu } from 'electron' import { ipcMain } from 'electron'
import fs from 'fs' import fs from 'fs'
import JSON5 from 'json5' import JSON5 from 'json5'
import path from 'path' import path from 'path'
const pk = require('../../package.json') const pk = require('../../../package.json')
const mitmproxyPath = path.join(__dirname, 'mitmproxy.js') const mitmproxyPath = path.join(__dirname, 'mitmproxy.js')
const log = require('../utils/util.log') process.env.DS_SYSPROXY_PATH = path.join(__dirname, '../extra/sysproxy.exe')
const log = require('../../utils/util.log')
const getDefaultConfigBasePath = function () { const getDefaultConfigBasePath = function () {
return DevSidecar.api.config.get().server.setting.userBasePath return DevSidecar.api.config.get().server.setting.userBasePath
} }
@ -170,25 +171,29 @@ function doMerge (defObj, newObj) {
return newObj2 return newObj2
} }
function invoke (api, param) {
let target = lodash.get(localApi, api)
if (target == null) {
target = lodash.get(DevSidecar.api, api)
}
if (target == null) {
log.info('找不到此接口方法:', api)
}
const ret = target(param)
// log.info('api:', api, 'ret:', ret)
return ret
}
export default { export default {
init (win) { install ({ win }) {
// 接收view的方法调用 // 接收view的方法调用
ipcMain.handle('apiInvoke', async (event, args) => { ipcMain.handle('apiInvoke', async (event, args) => {
const api = args[0] const api = args[0]
let target = lodash.get(localApi, api)
if (target == null) {
target = lodash.get(DevSidecar.api, api)
}
if (target == null) {
log.info('找不到此接口方法:', api)
}
let param let param
if (args.length >= 2) { if (args.length >= 2) {
param = args[1] param = args[1]
} }
const ret = target(param) return invoke(api, param)
// log.info('api:', api, 'ret:', ret)
return ret
}) })
// 注册从core里来的事件并转发给view // 注册从core里来的事件并转发给view
DevSidecar.api.event.register('status', (event) => { DevSidecar.api.event.register('status', (event) => {
@ -205,5 +210,6 @@ export default {
// 启动所有 // 启动所有
localApi.startup() localApi.startup()
}, },
devSidecar: DevSidecar devSidecar: DevSidecar,
invoke
} }

View File

@ -0,0 +1,19 @@
import api from './api/backend'
import tongji from './tongji/backend'
import update from './update/backend'
import fileSelector from './file-selector/backend'
const modules = {
api, // 核心接口模块
fileSelector, // 文件选择模块
tongji, // 统计模块
update // 自动更新
}
export default {
install (context) {
for (const module in modules) {
modules[module].install(context)
}
},
...modules
}

View File

@ -0,0 +1,21 @@
export default {
install (context) {
const { ipcMain, dialog, log } = context
ipcMain.on('file-selector', function (event, message) {
if (message.key === 'open') {
dialog.showOpenDialog({
properties: ['openFile'],
...message
}).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 => {
log.error('选择文件失败', err)
})
}
})
}
}

View File

@ -0,0 +1,23 @@
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.on('file-selector', (event, message) => {
console.log('selector', message)
if (message.key === 'selected') {
resolve(message.value)
} else {
reject(new Error('没有选择文件'))
}
api.ipc.on('file-selector', () => {})
})
})
}
}
}
export default {
install
}

View File

@ -0,0 +1,21 @@
// import api from './api/front'
import error from './error/front'
import tongji from './tongji/front'
import update from './update/front'
import fileSelector from './file-selector/front'
const modules = {
// api, // 核心接口模块
error,
fileSelector, // 文件选择模块
tongji, // 统计模块
update // 自动更新
}
export default {
install (app, api, router) {
for (const module in modules) {
modules[module].install(app, api, router)
}
},
...modules
}

View File

@ -1,15 +1,14 @@
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const server = require('@docmirror/mitmproxy') const server = require('@docmirror/mitmproxy')
const configPath = process.argv[2] const configPath = process.argv[2]
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
const configJson = fs.readFileSync(configPath) const configJson = fs.readFileSync(configPath)
const config = JSON.parse(configJson) const config = JSON.parse(configJson)
let scriptDir = '../extra/scripts/' let scriptDir = '../extra/scripts/'
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
scriptDir = '../extra/scripts/' scriptDir = '../extra/scripts/'
} }
config.setting.script.defaultDir = path.join(__dirname, scriptDir) config.setting.script.defaultDir = path.join(__dirname, scriptDir)
server.start(config) server.start(config)

View File

@ -0,0 +1,55 @@
/**
* first step
* @param {*} ipcMain
*/
const ebtMain = (ipcMain) => {
const isDevelopment = process.env.NODE_ENV !== 'production'
const request = require('request')
/* istanbul ignore else */
if (!(ipcMain && ipcMain.on)) {
throw new TypeError('require ipcMain')
}
// step 2
ipcMain.on('electron-baidu-tongji-message', (event, arg) => {
// electron 生产模式下是直接请求文件系统,没有 http 地址
// 前台拿不到 hm.js 的内容
request({
url: `https://hm.baidu.com/hm.js?${arg}`,
method: 'GET',
headers: {
Referer: 'https://hm.baidu.com/'
}
},
(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) {
// step 3
let text = body
/* istanbul ignore else */
if (!isDevelopment) {
// 百度统计可能改规则了,不统计 file:// 开始的请求
// 这里强制替换为 https
const target = '(h.c.b.su=h.c.b.u||"https://"+c.dm[0]+a[1]),h.c.b.u="https://"+c.dm[0]+'
const target2 = '"https://"+c.dm[0]+window.location.pathname+window.location.hash'
text = body.replace(rource, target).replace(/window.location.href/g, target2)
}
console.log('baidu tonji: ret')
event.sender.send('electron-baidu-tongji-reply', { text, isDevelopment })
}
})
})
}
export default {
install (context) {
ebtMain(context.ipcMain)
}
}

View File

@ -0,0 +1,62 @@
/**
* second step
* @param {*} ipcRenderer
* @param {*} siteId
* @param {*} router
*/
const ebtRenderer = (ipcRenderer, siteId, router) => {
/* istanbul ignore else */
if (!(ipcRenderer && ipcRenderer.on && ipcRenderer.send)) {
throw new TypeError('require ipcRenderer')
}
/* istanbul ignore else */
if (!(siteId && typeof siteId === 'string')) {
throw new TypeError('require siteId')
}
// step 4
ipcRenderer.on('electron-baidu-tongji-reply', (_, { text, isDevelopment }) => {
console.log('electron-baidu-tongji-reply')
/* istanbul ignore else */
if (isDevelopment) { document.body.classList.add('electron-baidu-tongji_dev') }
window._hmt = window._hmt || []
const hm = document.createElement('script')
hm.text = text
const head = document.getElementsByTagName('head')[0]
head.appendChild(hm)
// Vue单页应用时监听router的每次变化
// 把虚拟的url地址赋给百度统计的API接口
/* istanbul ignore else */
if (router && router.beforeEach) {
router.beforeEach((to, _, next) => {
/* istanbul ignore else */
if (to.path) {
window._hmt.push(['_trackPageview', '/#' + to.fullPath])
console.log('baidu trace', to.fullPath)
}
next()
})
}
})
// step 1
ipcRenderer.send('electron-baidu-tongji-message', siteId)
}
export default {
install (app, api, router) {
const BAIDU_SITE_ID = 'f2d170ce560aef0005b689f28697f852'
// 百度统计
const { ipcRenderer } = require('electron')
ebtRenderer(ipcRenderer, BAIDU_SITE_ID, router)
},
ebtRenderer
}

View File

@ -1,6 +1,5 @@
import { ipcMain, dialog } from 'electron' import { ipcMain } from 'electron'
import { autoUpdater } from 'electron-updater' import { autoUpdater } from 'electron-updater'
import log from '../utils/util.log'
import path from 'path' import path from 'path'
// win是所有窗口的引用 // win是所有窗口的引用
// const path = require('path') // 引入path模块 // const path = require('path') // 引入path模块
@ -8,7 +7,7 @@ import path from 'path'
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const isMac = process.platform === 'darwin' const isMac = process.platform === 'darwin'
// 检测更新在你想要检查更新的时候执行renderer事件触发后的操作自行编写 // 检测更新在你想要检查更新的时候执行renderer事件触发后的操作自行编写
function updateHandle (app, win, beforeQuit, updateUrl) { function updateHandle (app, win, beforeQuit, updateUrl, log) {
// // 更新前,删除本地安装包 ↓ // // 更新前,删除本地安装包 ↓
// const updaterCacheDirName = 'dev-sidecar-updater' // const updaterCacheDirName = 'dev-sidecar-updater'
// const updatePendingPath = path.join(autoUpdater.app.baseCachePath, updaterCacheDirName, 'pending') // const updatePendingPath = path.join(autoUpdater.app.baseCachePath, updaterCacheDirName, 'pending')
@ -58,10 +57,7 @@ function updateHandle (app, win, beforeQuit, updateUrl) {
log.info('download complete', info.version) log.info('download complete', info.version)
win.webContents.send('update', { win.webContents.send('update', {
key: 'downloaded', key: 'downloaded',
value: { value: info
version: info.version,
releaseData: info.releaseDate
}
}) })
}) })
@ -95,4 +91,20 @@ function updateHandle (app, win, beforeQuit, updateUrl) {
log.info('auto update inited') log.info('auto update inited')
return autoUpdater return autoUpdater
} }
export default updateHandle
export default {
install (context) {
const { app, win, beforeQuit, log } = context
let updateUrl = 'https://dev-sidecar.docmirror.cn/update/'
if (process.env.NODE_ENV === 'development') {
Object.defineProperty(app, 'isPackaged', {
get () {
return true
}
})
// updateUrl = 'https://dev-sidecar.docmirror.cn/update/'
updateUrl = 'http://localhost/dev-sidecar/'
}
updateHandle(app, win, beforeQuit, updateUrl, log)
}
}

View File

@ -78,11 +78,19 @@ function install (app, api) {
function newUpdateIsReady (value) { function newUpdateIsReady (value) {
updateParams.downloading = false updateParams.downloading = false
app.$confirm({ app.$confirm({
title: '新版本已准备好', title: `新版本(v${value.version})已准备好,是否立即升级?`,
content: `是否立即升级安装v${value.version}?`,
cancelText: '暂不升级', cancelText: '暂不升级',
okText: '立即升级', okText: '立即升级',
// content: h => <div><h4>{value.version}更新内容:</h4><div>{value.releaseNotes}</div></div>, content: h => {
console.log(value)
if (value.releaseNotes) {
const notes = []
for (const note of value.releaseNotes) {
notes.push(<li>{note}</li>)
}
return <div><div>更新内容</div><ol>{notes}</ol></div>
}
},
onOk () { onOk () {
console.log('OK') console.log('OK')
api.update.doUpdateNow() api.update.doUpdateNow()

View File

@ -7,9 +7,6 @@ import VueRouter from 'vue-router'
import routes from './view/router' import routes from './view/router'
import DsContainer from './view/components/container' import DsContainer from './view/components/container'
import './view/style/index.scss' import './view/style/index.scss'
import { ipcRenderer } from 'electron'
const tongji = require('./tongji')
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.use(antd) Vue.use(antd)
@ -28,12 +25,7 @@ view.initApi().then(async (api) => {
router, router,
render: h => h(App) render: h => h(App)
}).$mount('#app') }).$mount('#app')
view.initModules(app, router)
const BAIDU_SITE_ID = 'f2d170ce560aef0005b689f28697f852'
// 百度统计
tongji.ebtRenderer(ipcRenderer, BAIDU_SITE_ID, router)
view.initModules(app)
}) })
// fix vue-router NavigationDuplicated // fix vue-router NavigationDuplicated

View File

@ -1,103 +0,0 @@
const request = require('request')
/**
* first step
* @param {*} ipcMain
*/
const ebtMain = (ipcMain, isDevelopment) => {
/* istanbul ignore else */
if (!(ipcMain && ipcMain.on)) {
throw new TypeError('require ipcMain')
}
// step 2
ipcMain.on('electron-baidu-tongji-message', (event, arg) => {
// electron 生产模式下是直接请求文件系统,没有 http 地址
// 前台拿不到 hm.js 的内容
request({
url: `https://hm.baidu.com/hm.js?${arg}`,
method: 'GET',
headers: {
Referer: 'https://hm.baidu.com/'
}
},
(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) {
// step 3
let text = body
/* istanbul ignore else */
if (!isDevelopment) {
// 百度统计可能改规则了,不统计 file:// 开始的请求
// 这里强制替换为 https
const target = '(h.c.b.su=h.c.b.u||"https://"+c.dm[0]+a[1]),h.c.b.u="https://"+c.dm[0]+'
const target2 = '"https://"+c.dm[0]+window.location.pathname+window.location.hash'
text = body.replace(rource, target).replace(/window.location.href/g, target2)
}
console.log('baidu tonji: ret')
event.sender.send('electron-baidu-tongji-reply', { text, isDevelopment })
}
})
})
}
/**
* second step
* @param {*} ipcRenderer
* @param {*} siteId
* @param {*} router
*/
const ebtRenderer = (ipcRenderer, siteId, router) => {
/* istanbul ignore else */
if (!(ipcRenderer && ipcRenderer.on && ipcRenderer.send)) {
throw new TypeError('require ipcRenderer')
}
/* istanbul ignore else */
if (!(siteId && typeof siteId === 'string')) {
throw new TypeError('require siteId')
}
// step 4
ipcRenderer.on('electron-baidu-tongji-reply', (_, { text, isDevelopment }) => {
console.log('electron-baidu-tongji-reply')
/* istanbul ignore else */
if (isDevelopment) { document.body.classList.add('electron-baidu-tongji_dev') }
window._hmt = window._hmt || []
const hm = document.createElement('script')
hm.text = text
const head = document.getElementsByTagName('head')[0]
head.appendChild(hm)
// Vue单页应用时监听router的每次变化
// 把虚拟的url地址赋给百度统计的API接口
/* istanbul ignore else */
if (router && router.beforeEach) {
router.beforeEach((to, _, next) => {
/* istanbul ignore else */
if (to.path) {
window._hmt.push(['_trackPageview', '/#' + to.fullPath])
console.log('baidu trace', to.fullPath)
}
next()
})
}
})
// step 1
ipcRenderer.send('electron-baidu-tongji-message', siteId)
}
module.exports = { ebtMain, ebtRenderer }

View File

@ -3,11 +3,12 @@ const DevSidecar = require('@docmirror/dev-sidecar')
const getDefaultConfigBasePath = function () { const getDefaultConfigBasePath = function () {
return DevSidecar.api.config.get().server.setting.userBasePath return DevSidecar.api.config.get().server.setting.userBasePath
} }
const level = process.env.NODE_ENV === 'development' ? 'debug' : 'info'
const path = require('path') const path = require('path')
const filename = path.join(getDefaultConfigBasePath(), '/logs/gui.log') const filename = path.join(getDefaultConfigBasePath(), '/logs/gui.log')
log4js.configure({ log4js.configure({
appenders: { std: { type: 'stdout' }, file: { type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename } }, appenders: { std: { type: 'stdout' }, file: { type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename } },
categories: { default: { appenders: ['file', 'std'], level: 'info' } } categories: { default: { appenders: ['file', 'std'], level } }
}) })
const logger = log4js.getLogger('server') const logger = log4js.getLogger('server')
module.exports = logger module.exports = logger

View File

@ -1,5 +1,5 @@
import api, { apiInit } from './api' import api, { apiInit } from './api'
import modules from './modules' import modules from '../bridge/front'
import status from './status' import status from './status'
export default { export default {
initApi: apiInit, initApi: apiInit,
@ -9,7 +9,7 @@ export default {
Vue.prototype.$global = { setting } Vue.prototype.$global = { setting }
await status.install(api) await status.install(api)
}, },
initModules (app) { initModules (app, router) {
modules.install(app, api) modules.install(app, api, router)
} }
} }

View File

@ -1,9 +0,0 @@
import update from './update'
import error from './error'
export default {
install (app, api) {
error.install(app, api)
update.install(app, api)
}
}

View File

@ -38,8 +38,8 @@
<div>开启此项之后被代理应用关闭SSL校验也问题不大了</div> <div>开启此项之后被代理应用关闭SSL校验也问题不大了</div>
</a-form-item> </a-form-item>
<a-form-item label="根证书:" :label-col="labelCol" :wrapper-col="wrapperCol"> <a-form-item label="根证书:" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-input addon-before="Cert" addon-after="" v-model="config.server.setting.rootCaFile.certPath" ></a-input> <a-input-search addon-before="Cert" enter-button="" @search="onCrtSelect" v-model="config.server.setting.rootCaFile.certPath" />
<a-input addon-before="Key" addon-after="" v-model="config.server.setting.rootCaFile.keyPath" ></a-input> <a-input-search addon-before="Key" enter-button="" @search="onKeySelect" v-model="config.server.setting.rootCaFile.keyPath" />
</a-form-item> </a-form-item>
<a-form-item label="启用脚本" :label-col="labelCol" :wrapper-col="wrapperCol"> <a-form-item label="启用脚本" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-tooltip title="关闭后github的clone加速链接复制也将关闭"> <a-tooltip title="关闭后github的clone加速链接复制也将关闭">
@ -112,6 +112,18 @@ export default {
mounted () { mounted () {
}, },
methods: { methods: {
async onCrtSelect () {
const value = await this.$api.fileSelector.open()
if (value != null && value.length > 0) {
this.config.server.setting.rootCaFile.certPath = value[0]
}
},
async onKeySelect () {
const value = await this.$api.fileSelector.open()
if (value != null && value.length > 0) {
this.config.server.setting.rootCaFile.keyPath = value[0]
}
},
onJsonChange (json) { onJsonChange (json) {
}, },
ready () { ready () {
@ -148,7 +160,7 @@ export default {
}, },
async openLog () { async openLog () {
const dir = await this.$api.info.getConfigDir() const dir = await this.$api.info.getConfigDir()
this.$api.ipc.openPath(dir + '/logs/server.log') this.$api.ipc.openPath(dir + '/logs/')
} }
} }
} }

View File

@ -36,3 +36,10 @@
.md-mb-10{margin-bottom: 10px;} .md-mb-10{margin-bottom: 10px;}
.md-mb-15{margin-bottom: 15px;} .md-mb-15{margin-bottom: 15px;}
.md-mb-20{margin-bottom: 20px;} .md-mb-20{margin-bottom: 20px;}
ol{
margin-block-start: 0em;
margin-block-end: 0em;
padding-inline-start: 20px;
}

View File

@ -1,6 +1,6 @@
{ {
"name": "@docmirror/mitmproxy", "name": "@docmirror/mitmproxy",
"version": "1.2.1", "version": "1.2.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "@docmirror/mitmproxy", "name": "@docmirror/mitmproxy",
"version": "1.2.1", "version": "1.2.2",
"description": "", "description": "",
"main": "src/index.js", "main": "src/index.js",
"keywords": [ "keywords": [

View File

@ -39,7 +39,7 @@ class DynamicChoice {
if (this.count[item]) { if (this.count[item]) {
continue continue
} }
this.count[item] = { value: item, total: defaultTotal, error: 0, keepErrorCount: 0, successRate: 1 } this.count[item] = { value: item, total: defaultTotal, error: 0, keepErrorCount: 0, successRate: 0.5 }
defaultTotal-- defaultTotal--
} }
this.value = backupList.shift() this.value = backupList.shift()

View File

@ -49,7 +49,10 @@ module.exports = {
rOptions.port = rOptions.protocol === 'https:' ? 443 : 80 rOptions.port = rOptions.protocol === 'https:' ? 443 : 80
} }
log.info('proxy:', rOptions.hostname, proxyTarget) log.info('proxy:', rOptions.hostname, proxyTarget)
log.debug('proxy choice:', JSON.stringify(context.requestCount)) if (context.requestCount) {
log.debug('proxy choice:', JSON.stringify(context.requestCount))
}
return true return true
}, },
is (interceptOpt) { is (interceptOpt) {

View File

@ -71,6 +71,7 @@ const api = {
load (rootDir) { load (rootDir) {
scripts = {} scripts = {}
scripts.github = loadScript(readFile(rootDir, 'github.script')) scripts.github = loadScript(readFile(rootDir, 'github.script'))
scripts.google = loadScript(readFile(rootDir, 'google.js'))
scripts.jquery = { script: readFile(rootDir, 'jquery.min.js') } scripts.jquery = { script: readFile(rootDir, 'jquery.min.js') }
scripts.global = { script: readFile(rootDir, 'global.script') } scripts.global = { script: readFile(rootDir, 'global.script') }
return scripts return scripts

View File

@ -48,6 +48,7 @@ function injectScriptIntoHtml (tags, chunk, script) {
if (index < 0) { if (index < 0) {
continue continue
} }
console.log('insert script:', tag)
const scriptBuf = Buffer.from(script) const scriptBuf = Buffer.from(script)
const chunkNew = Buffer.alloc(chunk.length + scriptBuf.length) const chunkNew = Buffer.alloc(chunk.length + scriptBuf.length)
chunk.copy(chunkNew, 0, 0, index) chunk.copy(chunkNew, 0, 0, index)

View File

@ -1,10 +1,11 @@
const log4js = require('log4js') const log4js = require('log4js')
const proxyConfig = require('../lib/proxy/common/config') const proxyConfig = require('../lib/proxy/common/config')
const level = process.env.NODE_ENV === 'development' ? 'debug' : 'info'
const path = require('path') const path = require('path')
const filename = path.join(proxyConfig.getDefaultCABasePath(), '/logs/server.log') const filename = path.join(proxyConfig.getDefaultCABasePath(), '/logs/server.log')
log4js.configure({ log4js.configure({
appenders: { std: { type: 'stdout', level: 'debug' }, file: { type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename } }, appenders: { std: { type: 'stdout', level: 'debug' }, file: { type: 'file', pattern: 'yyyy-MM-dd', daysToKeep: 3, filename } },
categories: { default: { appenders: ['file', 'std'], level: 'info' } } categories: { default: { appenders: ['file', 'std'], level } }
}) })
const logger = log4js.getLogger('server') const logger = log4js.getLogger('server')
module.exports = logger module.exports = logger