fix: 修复插入脚本时部分字符乱码的问题
parent
7713bffdc0
commit
041a4b16a1
|
@ -29,7 +29,7 @@ module.exports = {
|
|||
'/.*': {
|
||||
proxy: 'github.com',
|
||||
backup: [
|
||||
'github.docmirror.cn/_proxy'
|
||||
'gh.docmirror.top/_proxy'
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
@ -28,7 +28,7 @@ module.exports = {
|
|||
const scriptTag = getScript(key, script.script)
|
||||
tags += '\r\n' + scriptTag
|
||||
}
|
||||
log.info('responseIntercept: append script', rOptions.hostname, rOptions.path)
|
||||
log.info('responseIntercept: insert script', rOptions.hostname, rOptions.path)
|
||||
return {
|
||||
head: tags
|
||||
}
|
||||
|
|
|
@ -4,6 +4,15 @@ const zlib = require('zlib')
|
|||
const url = require('url')
|
||||
|
||||
var httpUtil = {}
|
||||
httpUtil.getCharset = function (res) {
|
||||
const contentType = res.getHeader('content-type')
|
||||
const reg = /charset=(.*)/
|
||||
const matched = contentType.match(reg)
|
||||
if (matched) {
|
||||
return matched[1]
|
||||
}
|
||||
return 'utf-8'
|
||||
}
|
||||
httpUtil.isGzip = function (res) {
|
||||
var contentEncoding = res.headers['content-encoding']
|
||||
return !!(contentEncoding && contentEncoding.toLowerCase() === 'gzip')
|
||||
|
@ -12,34 +21,63 @@ httpUtil.isHtml = function (res) {
|
|||
var contentType = res.headers['content-type']
|
||||
return (typeof contentType !== 'undefined') && /text\/html|application\/xhtml\+xml/.test(contentType)
|
||||
}
|
||||
const HEAD = Buffer.from('</head>')
|
||||
const HEAD_UP = Buffer.from('</HEAD>')
|
||||
const BODY = Buffer.from('</body>')
|
||||
const BODY_UP = Buffer.from('</BODY>')
|
||||
|
||||
function injectScriptIntoHeadHtml (html, script) {
|
||||
html = html.replace(/(<\/head>)/i, function (match) {
|
||||
return script + match
|
||||
})
|
||||
return html
|
||||
}
|
||||
|
||||
function injectScriptIntoBodyHtml (html, script) {
|
||||
html = html.replace(/(<\/body>)/i, function (match) {
|
||||
return script + match
|
||||
})
|
||||
return html
|
||||
}
|
||||
|
||||
function chunkReplace (_this, chunk, enc, callback, append) {
|
||||
let chunkString = chunk.toString()
|
||||
function chunkByteReplace (_this, chunk, enc, callback, append) {
|
||||
if (append && append.head) {
|
||||
chunkString = injectScriptIntoHeadHtml(chunkString, append.head)
|
||||
const ret = injectScriptIntoHtml([HEAD, HEAD_UP], chunk, append.head)
|
||||
if (ret != null) {
|
||||
chunk = ret
|
||||
}
|
||||
}
|
||||
if (append && append.body) {
|
||||
chunkString = injectScriptIntoBodyHtml(chunkString, append.body)
|
||||
const ret = injectScriptIntoHtml([BODY, BODY_UP], chunk, append.body)
|
||||
if (ret != null) {
|
||||
chunk = ret
|
||||
}
|
||||
}
|
||||
_this.push(Buffer.from(chunkString))
|
||||
_this.push(chunk)
|
||||
callback()
|
||||
}
|
||||
function injectScriptIntoHtml (tags, chunk, script) {
|
||||
for (const tag of tags) {
|
||||
const index = chunk.indexOf(tag)
|
||||
if (index < 0) {
|
||||
continue
|
||||
}
|
||||
const scriptBuf = Buffer.from(script)
|
||||
const chunkNew = Buffer.alloc(chunk.length + scriptBuf.length)
|
||||
chunk.copy(chunkNew, 0, 0, index)
|
||||
scriptBuf.copy(chunkNew, index, 0)
|
||||
chunk.copy(chunkNew, index + scriptBuf.length, index)
|
||||
return chunkNew
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const contextPath = '/____ds_script____/'
|
||||
const monkey = require('../../monkey')
|
||||
module.exports = {
|
||||
|
||||
requestIntercept (context, req, res, ssl, next) {
|
||||
const { rOptions, log } = context
|
||||
if (rOptions.path.indexOf(contextPath) !== 0) {
|
||||
return
|
||||
}
|
||||
const urlPath = rOptions.path
|
||||
const filename = urlPath.replace(contextPath, '')
|
||||
|
||||
const script = monkey.get()[filename]
|
||||
|
||||
log.info('ds_script', filename, script != null)
|
||||
res.writeHead(200)
|
||||
res.write(script.script)
|
||||
res.end()
|
||||
return true
|
||||
},
|
||||
responseInterceptor (req, res, proxyReq, proxyRes, ssl, next, append) {
|
||||
if (!append.head && !append.body) {
|
||||
next()
|
||||
|
@ -52,6 +90,7 @@ module.exports = {
|
|||
})()
|
||||
if (!isHtml || contentLengthIsZero) {
|
||||
next()
|
||||
return
|
||||
} else {
|
||||
Object.keys(proxyRes.headers).forEach(function (key) {
|
||||
if (proxyRes.headers[key] !== undefined) {
|
||||
|
@ -88,11 +127,11 @@ module.exports = {
|
|||
if (isGzip) {
|
||||
proxyRes.pipe(new zlib.Gunzip())
|
||||
.pipe(through(function (chunk, enc, callback) {
|
||||
chunkReplace(this, chunk, enc, callback, append)
|
||||
chunkByteReplace(this, chunk, enc, callback, append)
|
||||
})).pipe(new zlib.Gzip()).pipe(res)
|
||||
} else {
|
||||
proxyRes.pipe(through(function (chunk, enc, callback) {
|
||||
chunkReplace(this, chunk, enc, callback, append)
|
||||
chunkByteReplace(this, chunk, enc, callback, append)
|
||||
})).pipe(res)
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
const contextPath = '/____ds_script____/'
|
||||
const monkey = require('../../monkey')
|
||||
module.exports = {
|
||||
requestIntercept (context, req, res, ssl, next) {
|
||||
const { rOptions, log } = context
|
||||
const urlPath = rOptions.path
|
||||
const filename = urlPath.replace(contextPath, '')
|
||||
|
||||
const script = monkey.get()[filename]
|
||||
|
||||
log.info('ds_script', filename, script != null)
|
||||
res.writeHead(200)
|
||||
res.write(script.script)
|
||||
res.end()
|
||||
return true
|
||||
},
|
||||
is (rOptions) {
|
||||
if (rOptions.path.indexOf(contextPath) !== 0) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -4,9 +4,10 @@ const commonUtil = require('../common/util')
|
|||
// const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i
|
||||
const DnsUtil = require('../../dns/index')
|
||||
const log = require('../../../utils/util.log')
|
||||
const HtmlMiddleware = require('../middleware/HtmlMiddleware')
|
||||
const RequestCounter = require('../../choice/RequestCounter')
|
||||
const ScriptMiddleware = require('../middleware/ScriptMiddleware')
|
||||
const InsertScriptMiddleware = require('../middleware/InsertScriptMiddleware')
|
||||
const defaultDns = require('dns')
|
||||
const MAX_SLOW_TIME = 8000 // 超过此时间 则认为太慢了
|
||||
// create requestHandler function
|
||||
module.exports = function createRequestHandler (createIntercepts, externalProxy, dnsConfig) {
|
||||
// return
|
||||
|
@ -30,7 +31,7 @@ module.exports = function createRequestHandler (createIntercepts, externalProxy,
|
|||
if (interceptors == null) {
|
||||
interceptors = []
|
||||
}
|
||||
let reqIncpts = interceptors.filter(item => { return item.requestIntercept != null })
|
||||
const reqIncpts = interceptors.filter(item => { return item.requestIntercept != null })
|
||||
const resIncpts = interceptors.filter(item => { return item.responseIntercept != null })
|
||||
|
||||
const requestInterceptorPromise = () => {
|
||||
|
@ -39,13 +40,7 @@ module.exports = function createRequestHandler (createIntercepts, externalProxy,
|
|||
resolve()
|
||||
}
|
||||
try {
|
||||
if (ScriptMiddleware.is(rOptions)) {
|
||||
if (reqIncpts == null) {
|
||||
reqIncpts = []
|
||||
}
|
||||
reqIncpts.unshift(ScriptMiddleware)
|
||||
}
|
||||
|
||||
reqIncpts.unshift(InsertScriptMiddleware)
|
||||
if (reqIncpts && reqIncpts.length > 0) {
|
||||
for (const reqIncpt of reqIncpts) {
|
||||
const goNext = reqIncpt.requestIntercept(context, req, res, ssl, next)
|
||||
|
@ -105,19 +100,20 @@ module.exports = function createRequestHandler (createIntercepts, externalProxy,
|
|||
if (ip !== hostname) {
|
||||
callback(null, ip, 4)
|
||||
} else {
|
||||
rOptions.lookup(hostname, options, callback)
|
||||
defaultDns.lookup(hostname, options, callback)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proxyReq = (rOptions.protocol === 'https:' ? https : http).request(rOptions, (proxyRes) => {
|
||||
const end = new Date().getTime()
|
||||
const cost = end - start
|
||||
if (rOptions.protocol === 'https:') {
|
||||
log.info('代理请求返回:', url, cost + 'ms')
|
||||
}
|
||||
if (cost > 8000) {
|
||||
if (cost > MAX_SLOW_TIME) {
|
||||
countSlow(isDnsIntercept)
|
||||
}
|
||||
resolve(proxyRes)
|
||||
|
@ -146,7 +142,7 @@ module.exports = function createRequestHandler (createIntercepts, externalProxy,
|
|||
const cost = end - start
|
||||
log.error('代理请求被取消', rOptions.hostname, rOptions.path, cost + 'ms')
|
||||
|
||||
if (cost > 8000) {
|
||||
if (cost > MAX_SLOW_TIME) {
|
||||
countSlow(isDnsIntercept)
|
||||
}
|
||||
|
||||
|
@ -212,7 +208,7 @@ module.exports = function createRequestHandler (createIntercepts, externalProxy,
|
|||
body += append.body
|
||||
}
|
||||
}
|
||||
HtmlMiddleware.responseInterceptor(req, res, proxyReq, proxyRes, ssl, next, { head, body })
|
||||
InsertScriptMiddleware.responseInterceptor(req, res, proxyReq, proxyRes, ssl, next, { head, body })
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
const _ = require('lodash')
|
||||
module.exports = (middlewares) => {
|
||||
if (middlewares) {
|
||||
if (Object.prototype.toString.call(middlewares) !== '[object Array]') {
|
||||
throw new TypeError('middlewares must be a array')
|
||||
}
|
||||
}
|
||||
//
|
||||
// const sslConnectInterceptors = []
|
||||
// const requestInterceptors = []
|
||||
// const responseInterceptors = []
|
||||
|
||||
_.each(middlewares, (m) => {
|
||||
if (m.buildIn === false || m.buildIn === 'false') {
|
||||
|
||||
} else {
|
||||
// m.name
|
||||
}
|
||||
})
|
||||
}
|
|
@ -5,3 +5,13 @@ console.log(ret)
|
|||
|
||||
const reg = new RegExp('^/[^/]+/[^/]+$')
|
||||
console.log('/greper/d2-crud-plus/blob/master/.eslintignore'.match(reg))
|
||||
|
||||
const chunk = Buffer.from('<head></head>')
|
||||
const script = '<script>a</script>'
|
||||
const index = chunk.indexOf('</head>')
|
||||
const scriptBuf = Buffer.from(script)
|
||||
const chunkNew = Buffer.alloc(chunk.length + scriptBuf.length)
|
||||
chunk.copy(chunkNew, 0, 0, index)
|
||||
scriptBuf.copy(chunkNew, index, 0)
|
||||
chunk.copy(chunkNew, index + scriptBuf.length, index)
|
||||
console.log(chunkNew.toString())
|
||||
|
|
Loading…
Reference in New Issue