bugfix: 修复同一域名不同端口共用fakeServer的Promise的问题

pull/375/head
王良 1 month ago
parent 02cbe17935
commit fb9226cf69

@ -1,5 +1,15 @@
const tlsUtils = require('./tlsUtils') const tlsUtils = require('./tlsUtils')
const https = require('https') // const https = require('https')
const log = require('../../../utils/util.log')
function arraysHaveSameElements (arr1, arr2) {
if (arr1.length !== arr2.length) {
return false
}
const sortedArr1 = [...arr1].sort()
const sortedArr2 = [...arr2].sort()
return sortedArr1.every((value, index) => value === sortedArr2[index])
}
module.exports = class CertAndKeyContainer { module.exports = class CertAndKeyContainer {
constructor ({ constructor ({
@ -26,17 +36,20 @@ module.exports = class CertAndKeyContainer {
getCertPromise (hostname, port) { getCertPromise (hostname, port) {
for (let i = 0; i < this.queue.length; i++) { for (let i = 0; i < this.queue.length; i++) {
const _certPromiseObj = this.queue[i] const _certPromiseObj = this.queue[i]
const mappingHostNames = _certPromiseObj.mappingHostNames if (_certPromiseObj.port === port) {
for (let j = 0; j < mappingHostNames.length; j++) { const mappingHostNames = _certPromiseObj.mappingHostNames
const DNSName = mappingHostNames[j] for (let j = 0; j < mappingHostNames.length; j++) {
if (tlsUtils.isMappingHostName(DNSName, hostname)) { const DNSName = mappingHostNames[j]
this.reRankCert(i) if (tlsUtils.isMappingHostName(DNSName, hostname)) {
return _certPromiseObj.promise this.reRankCert(i)
return _certPromiseObj.promise
}
} }
} }
} }
const certPromiseObj = { const certPromiseObj = {
port,
mappingHostNames: [hostname] // temporary hostname mappingHostNames: [hostname] // temporary hostname
} }
@ -45,8 +58,13 @@ module.exports = class CertAndKeyContainer {
const _resolve = (_certObj) => { const _resolve = (_certObj) => {
if (once) { if (once) {
once = false once = false
const mappingHostNames = tlsUtils.getMappingHostNamesFromCert(_certObj.cert) let newMappingHostNames = tlsUtils.getMappingHostNamesFromCert(_certObj.cert)
certPromiseObj.mappingHostNames = mappingHostNames // change newMappingHostNames = [...new Set(newMappingHostNames)]
if (!arraysHaveSameElements(newMappingHostNames, certPromiseObj.mappingHostNames)) {
log.info(`【getCertPromise - ${hostname}:${port}】Reset mappingHostNames: `, certPromiseObj.mappingHostNames, '变更为', newMappingHostNames)
certPromiseObj.mappingHostNames = newMappingHostNames // change
}
resolve(_certObj) resolve(_certObj)
} }
} }
@ -57,41 +75,41 @@ module.exports = class CertAndKeyContainer {
_resolve(certObj) _resolve(certObj)
} else { } else {
// 这个太慢了 // 这个太慢了
const preReq = https.request({ // const preReq = https.request({
port: port, // port: port,
hostname: hostname, // hostname: hostname,
path: '/', // path: '/',
method: 'HEAD' // method: 'HEAD'
}, (preRes) => { // }, (preRes) => {
try { // try {
const realCert = preRes.socket.getPeerCertificate() // const realCert = preRes.socket.getPeerCertificate()
if (realCert) { // if (realCert) {
try { // try {
certObj = tlsUtils.createFakeCertificateByCA(this.caKey, this.caCert, realCert) // certObj = tlsUtils.createFakeCertificateByCA(this.caKey, this.caCert, realCert)
} catch (error) { // } catch (error) {
certObj = tlsUtils.createFakeCertificateByDomain(this.caKey, this.caCert, hostname) // certObj = tlsUtils.createFakeCertificateByDomain(this.caKey, this.caCert, hostname)
} // }
} else { // } else {
certObj = tlsUtils.createFakeCertificateByDomain(this.caKey, this.caCert, hostname) // certObj = tlsUtils.createFakeCertificateByDomain(this.caKey, this.caCert, hostname)
} // }
_resolve(certObj) // _resolve(certObj)
} catch (e) { // } catch (e) {
reject(e) // reject(e)
} // }
}) // })
preReq.setTimeout(~~this.getCertSocketTimeout, () => { // preReq.setTimeout(~~this.getCertSocketTimeout, () => {
if (!certObj) { // if (!certObj) {
certObj = tlsUtils.createFakeCertificateByDomain(this.caKey, this.caCert, hostname) // certObj = tlsUtils.createFakeCertificateByDomain(this.caKey, this.caCert, hostname)
_resolve(certObj) // _resolve(certObj)
} // }
}) // })
preReq.on('error', (e) => { // preReq.on('error', (e) => {
if (!certObj) { // if (!certObj) {
certObj = tlsUtils.createFakeCertificateByDomain(this.caKey, this.caCert, hostname) // certObj = tlsUtils.createFakeCertificateByDomain(this.caKey, this.caCert, hostname)
_resolve(certObj) // _resolve(certObj)
} // }
}) // })
preReq.end() // preReq.end()
} }
}) })

@ -6,6 +6,16 @@ const pki = forge.pki
// const colors = require('colors') // const colors = require('colors')
const tls = require('tls') const tls = require('tls')
const log = require('../../../utils/util.log') const log = require('../../../utils/util.log')
function arraysHaveSameElements (arr1, arr2) {
if (arr1.length !== arr2.length) {
return false
}
const sortedArr1 = [...arr1].sort()
const sortedArr2 = [...arr2].sort()
return sortedArr1.every((value, index) => value === sortedArr2[index])
}
module.exports = class FakeServersCenter { module.exports = class FakeServersCenter {
constructor ({ maxLength = 256, requestHandler, upgradeHandler, caCert, caKey, getCertSocketTimeout }) { constructor ({ maxLength = 256, requestHandler, upgradeHandler, caCert, caKey, getCertSocketTimeout }) {
this.queue = [] this.queue = []
@ -36,17 +46,20 @@ module.exports = class FakeServersCenter {
getServerPromise (hostname, port) { getServerPromise (hostname, port) {
for (let i = 0; i < this.queue.length; i++) { for (let i = 0; i < this.queue.length; i++) {
const serverPromiseObj = this.queue[i] const serverPromiseObj = this.queue[i]
const mappingHostNames = serverPromiseObj.mappingHostNames if (serverPromiseObj.port === port) {
for (let j = 0; j < mappingHostNames.length; j++) { const mappingHostNames = serverPromiseObj.mappingHostNames
const DNSName = mappingHostNames[j] for (let j = 0; j < mappingHostNames.length; j++) {
if (tlsUtils.isMappingHostName(DNSName, hostname)) { const DNSName = mappingHostNames[j]
this.reRankServer(i) if (tlsUtils.isMappingHostName(DNSName, hostname)) {
return serverPromiseObj.promise this.reRankServer(i)
return serverPromiseObj.promise
}
} }
} }
} }
const serverPromiseObj = { const serverPromiseObj = {
port,
mappingHostNames: [hostname] // temporary hostname mappingHostNames: [hostname] // temporary hostname
} }
@ -75,7 +88,7 @@ module.exports = class FakeServersCenter {
cert, cert,
key, key,
server: fakeServer, server: fakeServer,
port: 0 // if prot === 0 ,should listen server's `listening` event. port: 0 // if port === 0 ,should listen server's `listening` event.
} }
serverPromiseObj.serverObj = serverObj serverPromiseObj.serverObj = serverObj
@ -88,14 +101,27 @@ module.exports = class FakeServersCenter {
log.debug(`【fakeServer request - ${hostname}:${port}\r\n----- req -----\r\n`, req, '\r\n----- res -----\r\n', res) log.debug(`【fakeServer request - ${hostname}:${port}\r\n----- req -----\r\n`, req, '\r\n----- res -----\r\n', res)
this.requestHandler(req, res, ssl) this.requestHandler(req, res, ssl)
}) })
let once = true
fakeServer.on('listening', () => { fakeServer.on('listening', () => {
log.debug(`【fakeServer listening - ${hostname}:${port}】no arguments...`) log.debug(`【fakeServer listening - ${hostname}:${port}】no arguments...`)
serverPromiseObj.mappingHostNames = tlsUtils.getMappingHostNamesFromCert(certObj.cert) if (cert && once) {
once = false
let newMappingHostNames = tlsUtils.getMappingHostNamesFromCert(cert)
newMappingHostNames = [...new Set(newMappingHostNames)]
if (!arraysHaveSameElements(serverPromiseObj.mappingHostNames, newMappingHostNames)) {
log.info(`【fakeServer listening - ${hostname}:${port}】Reset mappingHostNames: `, serverPromiseObj.mappingHostNames, '变更为', newMappingHostNames)
serverPromiseObj.mappingHostNames = newMappingHostNames
}
}
resolve(serverObj) resolve(serverObj)
}) })
fakeServer.on('upgrade', (req, socket, head) => { fakeServer.on('upgrade', (req, socket, head) => {
const ssl = true const ssl = true
log.debug(`【fakeServer upgrade - ${hostname}:${port}\r\n----- req -----\r\n`, req, '\r\n----- socket -----\r\n', socket, '\r\n----- head -----\r\n', head) if (process.env.NODE_ENV === 'development') {
log.debug(`【fakeServer upgrade - ${hostname}:${port}\r\n----- req -----\r\n`, req, '\r\n----- socket -----\r\n', socket, '\r\n----- head -----\r\n', head)
} else {
log.info(`【fakeServer upgrade - ${hostname}:${port}`, req.url)
}
this.upgradeHandler(req, socket, head, ssl) this.upgradeHandler(req, socket, head, ssl)
}) })

Loading…
Cancel
Save