diff --git a/packages/core/src/config/index.js b/packages/core/src/config/index.js index 9b03334da..bfbac4ca5 100644 --- a/packages/core/src/config/index.js +++ b/packages/core/src/config/index.js @@ -78,6 +78,11 @@ module.exports = { '^(/[^/]+){2}/pull/\\d+/open_with_menu.*$': { cacheDays: 7, desc: 'PR详情页:标题右边那个Code按钮的HTML代理请求地址,感觉上应该可以缓存。暂时先设置为缓存7天' + }, + '^(/[^/]+){2,}\\.(jpg|jpeg|png|gif)(\\?.*)?$': { + githubSpeedUp: true, + cacheDays: 7, + desc: '仓库内图片,重定向改为代理,并缓存7天。' } }, 'github-releases.githubusercontent.com': { diff --git a/packages/mitmproxy/src/lib/interceptor/impl/req/githubSpeedUp.js b/packages/mitmproxy/src/lib/interceptor/impl/req/githubSpeedUp.js new file mode 100644 index 000000000..f2d9c15fc --- /dev/null +++ b/packages/mitmproxy/src/lib/interceptor/impl/req/githubSpeedUp.js @@ -0,0 +1,37 @@ +const proxyApi = require('./proxy') + +module.exports = { + name: 'githubSpeedUp', + priority: 131, + requestIntercept (context, interceptOpt, req, res, ssl, next) { + const { rOptions, log } = context + + // 目前,只拦截github.com,后续可以继续拦截其他域名,做一些特殊处理 + if (rOptions.hostname !== 'github.com') { + return + } + + const url = `${rOptions.method} ➜ ${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${req.url}` + + // 判断是否为仓库内的图片文件 + const matched = req.url.match('^(/[^/]+){2}/raw(/[^/]+)+\\.(jpg|jpeg|png|gif)(\\?.*)?$') + if (matched) { + // 拼接代理地址 + const proxyConf = 'https://raw.githubusercontent.com' + req.url.replace('/raw/', '/') + + // 执行代理 + const proxyTarget = proxyApi.doProxy(proxyConf, rOptions, req) + + res.setHeader('DS-Interceptor', `githubSpeedUp: proxy -> ${proxyTarget}`) + + log.info(`githubSpeedUp intercept: ${url} -> ${proxyConf}`) + + return true + } + + return true // true代表请求结束 + }, + is (interceptOpt) { + return !!interceptOpt.githubSpeedUp + } +} diff --git a/packages/mitmproxy/src/lib/interceptor/impl/req/proxy.js b/packages/mitmproxy/src/lib/interceptor/impl/req/proxy.js index 9af56b14c..48955aab7 100644 --- a/packages/mitmproxy/src/lib/interceptor/impl/req/proxy.js +++ b/packages/mitmproxy/src/lib/interceptor/impl/req/proxy.js @@ -1,8 +1,51 @@ const url = require('url') const lodash = require('lodash') + +function doProxy (proxyConf, rOptions, req, interceptOpt) { + // 获取代理目标地址 + let proxyTarget + if (interceptOpt && interceptOpt.replace) { + const regexp = new RegExp(interceptOpt.replace) + proxyTarget = req.url.replace(regexp, proxyConf) + } else if (proxyConf.indexOf('http:') === 0 || proxyConf.indexOf('https:') === 0) { + proxyTarget = proxyConf + } else { + let uri = req.url + if (uri.indexOf('http') === 0) { + // eslint-disable-next-line node/no-deprecated-api + const URL = url.parse(uri) + uri = URL.path + } + proxyTarget = proxyConf + uri + } + + // eslint-disable-next-line + // no-template-curly-in-string + // eslint-disable-next-line no-template-curly-in-string + proxyTarget = proxyTarget.replace('${host}', rOptions.hostname) + + const proxy = proxyTarget.indexOf('http:') === 0 || proxyTarget.indexOf('https:') === 0 ? proxyTarget : rOptions.protocol + '//' + proxyTarget + // eslint-disable-next-line node/no-deprecated-api + const URL = url.parse(proxy) + rOptions.origional = lodash.cloneDeep(rOptions) // 备份原始请求参数 + delete rOptions.origional.agent + delete rOptions.origional.headers + rOptions.protocol = URL.protocol + rOptions.hostname = URL.host + rOptions.host = URL.host + rOptions.headers.host = URL.host + rOptions.path = URL.path + if (URL.port == null) { + rOptions.port = rOptions.protocol === 'https:' ? 443 : 80 + } + + return proxyTarget +} + module.exports = { name: 'proxy', priority: 121, + doProxy, requestIntercept (context, interceptOpt, req, res, ssl, next) { const { rOptions, log, RequestCounter } = context @@ -33,42 +76,8 @@ module.exports = { } } - // 获取代理目标地址 - let proxyTarget - if (interceptOpt.replace) { - const regexp = new RegExp(interceptOpt.replace) - proxyTarget = req.url.replace(regexp, proxyConf) - } else if (proxyConf.indexOf('http:') === 0 || proxyConf.indexOf('https:') === 0) { - proxyTarget = proxyConf - } else { - let uri = req.url - if (uri.indexOf('http') === 0) { - // eslint-disable-next-line node/no-deprecated-api - const URL = url.parse(uri) - uri = URL.path - } - proxyTarget = proxyConf + uri - } - - // eslint-disable-next-line - // no-template-curly-in-string - // eslint-disable-next-line no-template-curly-in-string - proxyTarget = proxyTarget.replace('${host}', rOptions.hostname) - - const proxy = proxyTarget.indexOf('http') === 0 ? proxyTarget : rOptions.protocol + '//' + proxyTarget - // eslint-disable-next-line node/no-deprecated-api - const URL = url.parse(proxy) - rOptions.origional = lodash.cloneDeep(rOptions) // 备份原始请求参数 - delete rOptions.origional.agent - delete rOptions.origional.headers - rOptions.protocol = URL.protocol - rOptions.hostname = URL.host - rOptions.host = URL.host - rOptions.headers.host = URL.host - rOptions.path = URL.path - if (URL.port == null) { - rOptions.port = rOptions.protocol === 'https:' ? 443 : 80 - } + // 替换 rOptions 中的地址,并返回代理目标地址 + const proxyTarget = doProxy(proxyConf, rOptions, req, interceptOpt) if (context.requestCount) { log.info('proxy choice:', JSON.stringify(context.requestCount)) diff --git a/packages/mitmproxy/src/lib/interceptor/index.js b/packages/mitmproxy/src/lib/interceptor/index.js index 8f4a72269..e0e046c00 100644 --- a/packages/mitmproxy/src/lib/interceptor/index.js +++ b/packages/mitmproxy/src/lib/interceptor/index.js @@ -10,6 +10,8 @@ const cacheReq = require('./impl/req/cacheReq') const proxy = require('./impl/req/proxy') const sni = require('./impl/req/sni') +const githubSpeedUp = require('./impl/req/githubSpeedUp') + // response interceptor impls const cacheRes = require('./impl/res/cacheRes') const script = require('./impl/res/script') @@ -20,6 +22,7 @@ module.exports = [ success, redirect, abort, cacheReq, proxy, sni, + githubSpeedUp, // response interceptor impls cacheRes, script