feature: proxy、redirect拦截器配置,支持域名正则匹配占位符替换。(之前仅支持path匹配替换)
							parent
							
								
									217ce9d972
								
							
						
					
					
						commit
						e47cf82d34
					
				| 
						 | 
				
			
			@ -111,7 +111,7 @@ function checkIsLimitConfig (id, api) {
 | 
			
		|||
module.exports = {
 | 
			
		||||
  name: 'baiduOcr',
 | 
			
		||||
  priority: 131,
 | 
			
		||||
  requestIntercept (context, interceptOpt, req, res, ssl, next, matched) {
 | 
			
		||||
  requestIntercept (context, interceptOpt, req, res, ssl, next) {
 | 
			
		||||
    const { rOptions, log } = context
 | 
			
		||||
 | 
			
		||||
    const headers = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,21 +1,29 @@
 | 
			
		|||
const url = require('node:url')
 | 
			
		||||
const lodash = require('lodash')
 | 
			
		||||
 | 
			
		||||
function replacePlaceholder0 (url, matched, pre) {
 | 
			
		||||
  if (matched) {
 | 
			
		||||
    for (let i = 0; i < matched.length; i++) {
 | 
			
		||||
      url = url.replace(`\${${pre}[${i}]}`, matched[i] || '')
 | 
			
		||||
    }
 | 
			
		||||
    if (matched.groups) {
 | 
			
		||||
      for (const key in matched.groups) {
 | 
			
		||||
        url = url.replace(`\${${key}}`, matched.groups[key] || '')
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return url
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 替换占位符
 | 
			
		||||
function replacePlaceholder (url, rOptions, matched) {
 | 
			
		||||
function replacePlaceholder (url, rOptions, pathMatched, hostnameMatched) {
 | 
			
		||||
  if (url.includes('${')) {
 | 
			
		||||
    // eslint-disable-next-line no-template-curly-in-string
 | 
			
		||||
    url = url.replace('${host}', rOptions.hostname)
 | 
			
		||||
 | 
			
		||||
    if (matched && url.includes('${')) {
 | 
			
		||||
      for (let i = 0; i < matched.length; i++) {
 | 
			
		||||
        url = url.replace(`\${m[${i}]}`, matched[i] == null ? '' : matched[i])
 | 
			
		||||
      }
 | 
			
		||||
      if (matched.groups) {
 | 
			
		||||
        for (const key in matched.groups) {
 | 
			
		||||
          url = url.replace(`\${${key}}`, matched.groups[key] == null ? '' : matched.groups[key])
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    if (url.includes('${')) {
 | 
			
		||||
      url = replacePlaceholder0(url, pathMatched, 'p')
 | 
			
		||||
      url = replacePlaceholder0(url, hostnameMatched, 'h')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 移除多余的占位符
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +35,7 @@ function replacePlaceholder (url, rOptions, matched) {
 | 
			
		|||
  return url
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function buildTargetUrl (rOptions, urlConf, interceptOpt, matched) {
 | 
			
		||||
function buildTargetUrl (rOptions, urlConf, interceptOpt, matched, hostnameMatched) {
 | 
			
		||||
  let targetUrl
 | 
			
		||||
  if (interceptOpt && interceptOpt.replace) {
 | 
			
		||||
    const regexp = new RegExp(interceptOpt.replace)
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +53,7 @@ function buildTargetUrl (rOptions, urlConf, interceptOpt, matched) {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  // 替换占位符
 | 
			
		||||
  targetUrl = replacePlaceholder(targetUrl, rOptions, matched)
 | 
			
		||||
  targetUrl = replacePlaceholder(targetUrl, rOptions, matched, hostnameMatched)
 | 
			
		||||
 | 
			
		||||
  // 拼接协议
 | 
			
		||||
  targetUrl = targetUrl.indexOf('http:') === 0 || targetUrl.indexOf('https:') === 0 ? targetUrl : `${rOptions.protocol}//${targetUrl}`
 | 
			
		||||
| 
						 | 
				
			
			@ -53,9 +61,9 @@ function buildTargetUrl (rOptions, urlConf, interceptOpt, matched) {
 | 
			
		|||
  return targetUrl
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function doProxy (proxyConf, rOptions, req, interceptOpt, matched) {
 | 
			
		||||
function doProxy (proxyConf, rOptions, req, interceptOpt, matched, hostnameMatched) {
 | 
			
		||||
  // 获取代理目标地址
 | 
			
		||||
  const proxyTarget = buildTargetUrl(rOptions, proxyConf, interceptOpt, matched)
 | 
			
		||||
  const proxyTarget = buildTargetUrl(rOptions, proxyConf, interceptOpt, matched, hostnameMatched)
 | 
			
		||||
 | 
			
		||||
  // 替换rOptions的属性
 | 
			
		||||
  // eslint-disable-next-line node/no-deprecated-api
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +89,7 @@ module.exports = {
 | 
			
		|||
  replacePlaceholder,
 | 
			
		||||
  buildTargetUrl,
 | 
			
		||||
  doProxy,
 | 
			
		||||
  requestIntercept (context, interceptOpt, req, res, ssl, next, matched) {
 | 
			
		||||
  requestIntercept (context, interceptOpt, req, res, ssl, next, matched, hostnameMatched) {
 | 
			
		||||
    const { rOptions, log, RequestCounter } = context
 | 
			
		||||
 | 
			
		||||
    const originHostname = rOptions.hostname
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +120,7 @@ module.exports = {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    // 替换 rOptions 中的地址,并返回代理目标地址
 | 
			
		||||
    const proxyTarget = doProxy(proxyConf, rOptions, req, interceptOpt, matched)
 | 
			
		||||
    const proxyTarget = doProxy(proxyConf, rOptions, req, interceptOpt, matched, hostnameMatched)
 | 
			
		||||
 | 
			
		||||
    if (context.requestCount) {
 | 
			
		||||
      log.info('proxy choice:', JSON.stringify(context.requestCount))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,11 +3,11 @@ const proxyApi = require('./proxy')
 | 
			
		|||
module.exports = {
 | 
			
		||||
  name: 'redirect',
 | 
			
		||||
  priority: 105,
 | 
			
		||||
  requestIntercept (context, interceptOpt, req, res, ssl, next, matched) {
 | 
			
		||||
  requestIntercept (context, interceptOpt, req, res, ssl, next, matched, hostnameMatched) {
 | 
			
		||||
    const { rOptions, log } = context
 | 
			
		||||
 | 
			
		||||
    // 获取重定向目标地址
 | 
			
		||||
    const redirect = proxyApi.buildTargetUrl(rOptions, interceptOpt.redirect, interceptOpt, matched)
 | 
			
		||||
    const redirect = proxyApi.buildTargetUrl(rOptions, interceptOpt.redirect, interceptOpt, matched, hostnameMatched)
 | 
			
		||||
 | 
			
		||||
    const headers = {
 | 
			
		||||
      'Location': redirect,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -186,12 +186,12 @@ module.exports = (serverConfig) => {
 | 
			
		|||
            if (impl.requestIntercept) {
 | 
			
		||||
              // req拦截器
 | 
			
		||||
              interceptor.requestIntercept = (context, req, res, ssl, next) => {
 | 
			
		||||
                return impl.requestIntercept(context, interceptOpt, req, res, ssl, next, matched)
 | 
			
		||||
                return impl.requestIntercept(context, interceptOpt, req, res, ssl, next, matched, interceptOpts.matched)
 | 
			
		||||
              }
 | 
			
		||||
            } else if (impl.responseIntercept) {
 | 
			
		||||
              // res拦截器
 | 
			
		||||
              interceptor.responseIntercept = (context, req, res, proxyReq, proxyRes, ssl, next) => {
 | 
			
		||||
                return impl.responseIntercept(context, interceptOpt, req, res, proxyReq, proxyRes, ssl, next, matched)
 | 
			
		||||
                return impl.responseIntercept(context, interceptOpt, req, res, proxyReq, proxyRes, ssl, next, matched, interceptOpts.matched)
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,10 +141,29 @@ function matchHostnameAll (hostMap, hostname, action) {
 | 
			
		|||
    // }
 | 
			
		||||
 | 
			
		||||
    // 正则表达式匹配
 | 
			
		||||
    if (hostname.match(regexp)) {
 | 
			
		||||
    const matched = hostname.match(regexp)
 | 
			
		||||
    if (matched) {
 | 
			
		||||
      value = hostMap[regexp]
 | 
			
		||||
      log.debug(`matchHostname-one: ${action}: '${hostname}' -> { "${regexp}": ${JSON.stringify(value)} }`)
 | 
			
		||||
      values = merge(values, value)
 | 
			
		||||
 | 
			
		||||
      // 设置matched
 | 
			
		||||
      if (matched.length > 1) {
 | 
			
		||||
        if (values.matched) {
 | 
			
		||||
          // 合并array
 | 
			
		||||
          matched.shift()
 | 
			
		||||
          values.matched = [...values.matched, ...matched] // 拼接上多个matched
 | 
			
		||||
 | 
			
		||||
          // 合并groups
 | 
			
		||||
          if (matched.groups) {
 | 
			
		||||
            values.matched.groups = merge(values.matched.groups, matched.groups)
 | 
			
		||||
          } else {
 | 
			
		||||
            values.matched.groups = matched.groups
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          values.matched = matched
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue