94 lines
2.8 KiB
JavaScript
94 lines
2.8 KiB
JavaScript
const url = require('url')
|
|
const pac = require('./source/pac')
|
|
const matchUtil = require('../../../utils/util.match')
|
|
const lodash = require('lodash')
|
|
function matched (hostname, regexpMap) {
|
|
const ret1 = matchUtil.matchHostname(regexpMap, hostname)
|
|
if (ret1) {
|
|
return true
|
|
}
|
|
const ret = pac.FindProxyForURL('https://' + hostname, hostname)
|
|
if (ret && ret.indexOf('PROXY ') === 0) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
module.exports = function createOverWallIntercept (overWallConfig) {
|
|
if (!overWallConfig || overWallConfig.enabled !== true) {
|
|
return null
|
|
}
|
|
let server = overWallConfig.server
|
|
let keys = Object.keys(server)
|
|
if (keys.length === 0) {
|
|
server = overWallConfig.serverDefault
|
|
keys = Object.keys(server)
|
|
}
|
|
if (keys.length === 0) {
|
|
return null
|
|
}
|
|
const regexpMap = matchUtil.domainMapRegexply(overWallConfig.targets)
|
|
return {
|
|
sslConnectInterceptor: (req, cltSocket, head) => {
|
|
const hostname = req.url.split(':')[0]
|
|
return matched(hostname, regexpMap)
|
|
},
|
|
requestIntercept (context, req, res, ssl, next) {
|
|
const { rOptions, log, RequestCounter } = context
|
|
if (rOptions.protocol === 'http:') {
|
|
return
|
|
}
|
|
const hostname = rOptions.hostname
|
|
if (!matched(hostname, regexpMap)) {
|
|
return
|
|
}
|
|
const cacheKey = '__over_wall_proxy__'
|
|
let proxyServer = keys[0]
|
|
if (RequestCounter && keys.length > 1) {
|
|
const count = RequestCounter.getOrCreate(cacheKey, keys)
|
|
if (count.value == null) {
|
|
count.doRank()
|
|
}
|
|
if (count.value == null) {
|
|
log.error('count value is null', count)
|
|
} else {
|
|
count.doCount(count.value)
|
|
proxyServer = count.value
|
|
context.requestCount = {
|
|
key: cacheKey,
|
|
value: count.value,
|
|
count
|
|
}
|
|
}
|
|
}
|
|
|
|
const domain = proxyServer
|
|
const path = server[domain].path
|
|
const password = server[domain].password
|
|
const proxyTarget = domain + '/' + path + '/' + hostname + req.url
|
|
|
|
// const backup = interceptOpt.backup
|
|
const proxy = proxyTarget.indexOf('http') === 0 ? proxyTarget : (rOptions.protocol + '//' + proxyTarget)
|
|
// eslint-disable-next-line node/no-deprecated-api
|
|
const URL = url.parse(proxy)
|
|
rOptions.protocol = URL.protocol
|
|
rOptions.hostname = URL.host
|
|
rOptions.host = URL.host
|
|
rOptions.headers.host = URL.host
|
|
if (password) {
|
|
rOptions.headers.dspassword = password
|
|
}
|
|
rOptions.path = URL.path
|
|
if (URL.port == null) {
|
|
rOptions.port = rOptions.protocol === 'https:' ? 443 : 80
|
|
}
|
|
log.info('OverWall:', rOptions.hostname, proxyTarget)
|
|
if (context.requestCount) {
|
|
log.debug('OverWall choice:', JSON.stringify(context.requestCount))
|
|
}
|
|
|
|
return true
|
|
}
|
|
}
|
|
}
|