forked from Akkariiin/electron-ssr
-
Notifications
You must be signed in to change notification settings - Fork 509
/
pac.js
118 lines (112 loc) · 3.34 KB
/
pac.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/**
* pac文件下载更新等
*/
import http from 'http'
import httpShutdown from 'http-shutdown'
import { parse } from 'url'
import { dialog } from 'electron'
import { readFile, writeFile, pathExists } from 'fs-extra'
import logger from './logger'
import { request } from '../shared/utils'
import bootstrapPromise, { pacPath } from './bootstrap'
import { currentConfig, appConfig$ } from './data'
import { isHostPortValid } from './port'
let pacContent
let pacServer
httpShutdown.extend()
/**
* 下载pac文件
*/
export async function downloadPac (force = false) {
await bootstrapPromise
const pacExisted = await pathExists(pacPath)
if (force || !pacExisted) {
logger.debug('start download pac')
const pac = await request('https://raw.githubusercontent.com/shadowsocksrr/pac.txt/pac/pac.txt')
pacContent = pac
return await writeFile(pacPath, pac)
}
}
function readPac () {
return new Promise(resolve => {
if (!pacContent) {
resolve(readFile(pacPath))
} else {
resolve(pacContent)
}
})
}
/**
* pac server
*/
export async function serverPac (appConfig, isProxyStarted) {
if (isProxyStarted) {
const host = currentConfig.shareOverLan ? '0.0.0.0' : '127.0.0.1'
const port = appConfig.pacPort !== undefined ? appConfig.pacPort : currentConfig.pacPort || 1240
isHostPortValid(host, port).then(() => {
pacServer = http.createServer((req, res) => {
if (parse(req.url).pathname === '/proxy.pac') {
downloadPac().then(() => {
return readPac()
}).then(buffer => buffer.toString()).then(text => {
res.writeHead(200, {
'Content-Type': 'application/x-ns-proxy-autoconfig',
'Connection': 'close'
})
res.write(text.replace(/__PROXY__/g, `SOCKS5 127.0.0.1:${appConfig.localPort}; SOCKS 127.0.0.1:${appConfig.localPort}; PROXY 127.0.0.1:${appConfig.localPort}; ${appConfig.httpProxyEnable ? 'PROXY 127.0.0.1:' + appConfig.httpProxyPort + ';' : ''} DIRECT`))
res.end()
})
} else {
res.writeHead(200)
res.end()
}
}).withShutdown().listen(port, host)
.on('listening', () => {
logger.info(`pac server listen at: ${host}:${port}`)
})
.once('error', err => {
logger.error(`pac server error: ${err}`)
pacServer.shutdown()
})
}).catch(() => {
dialog.showMessageBox({
type: 'warning',
title: '警告',
message: `PAC端口 ${port} 被占用`
})
})
}
}
/**
* 关闭pac服务
*/
export async function stopPacServer () {
if (pacServer && pacServer.listening) {
return new Promise((resolve, reject) => {
pacServer.shutdown(err => {
if (err) {
logger.warn(`close pac server error: ${err}`)
reject()
} else {
logger.info('pac server closed.')
resolve()
}
})
})
}
return Promise.resolve()
}
// 监听配置变化
appConfig$.subscribe(data => {
const [appConfig, changed, , isProxyStarted, isOldProxyStarted] = data
// 初始化
if (changed.length === 0) {
serverPac(appConfig, isProxyStarted)
} else {
if (changed.indexOf('pacPort') > -1 || isProxyStarted !== isOldProxyStarted) {
stopPacServer().then(() => {
serverPac(appConfig, isProxyStarted)
})
}
}
})