@@ -1403,6 +1403,11 @@ async function 读取config_JSON(env, hostname, userID, 重置配置 = false) {
14031403 账号 : 我的SOCKS5账号 ,
14041404 白名单 : SOCKS5白名单 ,
14051405 } ,
1406+ 路径模板 : {
1407+ PROXYIP : "proxyip={{IP:PORT}}" ,
1408+ SOCKS5 : { 全局 : "socks5://{{IP:PORT}}" , 标准 : "socks5={{IP:PORT}}" } ,
1409+ HTTP : { 全局 : "http://{{IP:PORT}}" , 标准 : "http={{IP:PORT}}" } ,
1410+ } ,
14061411 } ,
14071412 TG : {
14081413 启用 : false ,
@@ -1448,15 +1453,35 @@ async function 读取config_JSON(env, hostname, userID, 重置配置 = false) {
14481453 if ( env . PATH ) config_JSON . PATH = env . PATH . startsWith ( '/' ) ? env . PATH : '/' + env . PATH ;
14491454 else if ( ! config_JSON . PATH ) config_JSON . PATH = '/' ;
14501455
1451- const { SOCKS5 : 袜子五 , PROXYIP : 反代挨批 } = config_JSON . 反代 ;
1452- const 路径反代参数 = 袜子五 . 启用
1453- ? `${ 袜子五 . 启用 } ${ 袜子五 . 全局 ? '://' : '=' } ${ 袜子五 . 账号 } `
1454- : 反代挨批 !== 'auto' ? `proxyip=${ 反代挨批 } ` : '' ;
1456+ if ( ! config_JSON . 反代 . 路径模板 ?. PROXYIP ) {
1457+ config_JSON . 反代 . 路径模板 = {
1458+ PROXYIP : "proxyip={{IP:PORT}}" ,
1459+ SOCKS5 : { 全局 : "socks5://{{IP:PORT}}" , 标准 : "socks5={{IP:PORT}}" } ,
1460+ HTTP : { 全局 : "http://{{IP:PORT}}" , 标准 : "http={{IP:PORT}}" } ,
1461+ } ;
1462+ }
1463+
1464+ const { SOCKS5 : 袜子五 , PROXYIP : 反代挨批 , 路径模板 } = config_JSON . 反代 ;
1465+ const 代理配置 = 路径模板 [ 袜子五 . 启用 ?. toUpperCase ( ) ] ;
1466+ const 占位符 = '{{IP:PORT}}' ;
1467+
1468+ let 路径反代参数 = '' ;
1469+ if ( 代理配置 && 袜子五 . 账号 ) 路径反代参数 = ( 袜子五 . 全局 ? 代理配置 . 全局 : 代理配置 . 标准 ) . replace ( 占位符 , 袜子五 . 账号 ) ;
1470+ else if ( 反代挨批 !== 'auto' ) 路径反代参数 = 路径模板 . PROXYIP . replace ( 占位符 , 反代挨批 ) ;
1471+
1472+ let 反代查询参数 = '' ;
1473+ if ( 路径反代参数 . includes ( '?' ) ) {
1474+ const [ 反代路径部分 , 反代查询部分 ] = 路径反代参数 . split ( '?' ) ;
1475+ 路径反代参数 = 反代路径部分 ;
1476+ 反代查询参数 = 反代查询部分 ;
1477+ }
1478+
14551479 config_JSON . PATH = config_JSON . PATH . replace ( 路径反代参数 , '' ) . replace ( '//' , '/' ) ;
14561480 const normalizedPath = config_JSON . PATH === '/' ? '' : config_JSON . PATH . replace ( / \/ + (? = \? | $ ) / , '' ) . replace ( / \/ + $ / , '' ) ;
14571481 const [ 路径部分 , ...查询数组 ] = normalizedPath . split ( '?' ) ;
14581482 const 查询部分 = 查询数组 . length ? '?' + 查询数组 . join ( '?' ) : '' ;
1459- config_JSON . 完整节点路径 = ( 路径部分 || '/' ) + ( 路径部分 && 路径反代参数 ? '/' : '' ) + 路径反代参数 + 查询部分 + ( config_JSON . 启用0RTT ? ( 查询部分 ? '&' : '?' ) + 'ed=2560' : '' ) ;
1483+ const 最终查询部分 = 反代查询参数 ? ( 查询部分 ? 查询部分 + '&' + 反代查询参数 : '?' + 反代查询参数 ) : 查询部分 ;
1484+ config_JSON . 完整节点路径 = ( 路径部分 || '/' ) + ( 路径部分 && 路径反代参数 ? '/' : '' ) + 路径反代参数 + 最终查询部分 + ( config_JSON . 启用0RTT ? ( 最终查询部分 ? '&' : '?' ) + 'ed=2560' : '' ) ;
14601485
14611486 if ( ! config_JSON . TLS分片 && config_JSON . TLS分片 !== null ) config_JSON . TLS分片 = null ;
14621487 const TLS分片参数 = config_JSON . TLS分片 == 'Shadowrocket' ? `&fragment=${ encodeURIComponent ( '1,40-60,30-50,tlshello' ) } ` : config_JSON . TLS分片 == 'Happ' ? `&fragment=${ encodeURIComponent ( '3,1,tlshello' ) } ` : '' ;
@@ -1703,50 +1728,86 @@ async function 反代参数获取(request) {
17031728 我的SOCKS5账号 = searchParams . get ( 'socks5' ) || searchParams . get ( 'http' ) || null ;
17041729 启用SOCKS5全局反代 = searchParams . has ( 'globalproxy' ) || false ;
17051730
1706- // 统一处理反代IP参数 (优先级最高,使用正则一次匹配)
1707- const proxyMatch = pathLower . match ( / \/ ( p r o x y i p [ . = ] | p y i p = | i p = ) ( [ ^ / ? ] + ) / ) ;
1731+ // 辅助函数:解析代理协议URL (socks5://... 或 http://...)
1732+ const 解析代理URL = ( proxyUrl , 默认全局 = true ) => {
1733+ const protocolMatch = proxyUrl . match ( / ^ ( s o c k s 5 | h t t p ) : \/ \/ ( .+ ) $ / i) ;
1734+ if ( ! protocolMatch ) return false ;
1735+ 启用SOCKS5反代 = protocolMatch [ 1 ] . toLowerCase ( ) ;
1736+ 我的SOCKS5账号 = protocolMatch [ 2 ] . split ( '/' ) [ 0 ] ;
1737+ 启用SOCKS5全局反代 = 默认全局 || 启用SOCKS5全局反代 ;
1738+ return true ;
1739+ } ;
1740+
1741+ // 辅助函数:从路径值中提取干净的地址(移除后续路径段)
1742+ const 提取路径值 = ( rawValue ) => {
1743+ if ( rawValue . includes ( '://' ) ) {
1744+ // 协议URL:保留 protocol://user:pass@host:port,移除后续路径
1745+ const protocolPart = rawValue . split ( '://' ) ;
1746+ if ( protocolPart . length === 2 ) {
1747+ const [ protocol , afterProtocol ] = protocolPart ;
1748+ const firstSlashIndex = afterProtocol . indexOf ( '/' ) ;
1749+ if ( firstSlashIndex > 0 ) {
1750+ return protocol + '://' + afterProtocol . substring ( 0 , firstSlashIndex ) ;
1751+ }
1752+ }
1753+ } else {
1754+ // 普通IP:PORT:只保留到第一个 /
1755+ const firstSlashIndex = rawValue . indexOf ( '/' ) ;
1756+ if ( firstSlashIndex > 0 ) {
1757+ return rawValue . substring ( 0 , firstSlashIndex ) ;
1758+ }
1759+ }
1760+ return rawValue ;
1761+ } ;
1762+
1763+ // ==================== 第一步:处理 query 参数 ====================
1764+ // 优先级最高:?proxyip=, ?socks5=, ?http=
1765+ let socksMatch , proxyMatch ;
17081766 if ( searchParams . has ( 'proxyip' ) ) {
17091767 const 路参IP = searchParams . get ( 'proxyip' ) ;
1710- 反代IP = 路参IP . includes ( ',' ) ? 路参IP . split ( ',' ) [ Math . floor ( Math . random ( ) * 路参IP . split ( ',' ) . length ) ] : 路参IP ;
1711- 启用反代兜底 = false ;
1712- return ;
1713- } else if ( proxyMatch ) {
1714- const 路参IP = proxyMatch [ 1 ] === 'proxyip.' ? `proxyip. ${ proxyMatch [ 2 ] } ` : proxyMatch [ 2 ] ;
1715- 反代IP = 路参IP . includes ( ',' ) ? 路参IP . split ( ',' ) [ Math . floor ( Math . random ( ) * 路参IP . split ( ',' ) . length ) ] : 路参IP ;
1716- 启用反代兜底 = false ;
1717- return ;
1768+ // proxyip 值以 socks5:// 或 http:// 开头,视为对应协议处理
1769+ if ( 解析代理URL ( 路参IP ) ) { /* 继续到下方统一解析 */ }
1770+ else {
1771+ // 否则作为 IP 反代
1772+ 反代IP = 路参IP . includes ( ',' ) ? 路参IP . split ( ',' ) [ Math . floor ( Math . random ( ) * 路参IP . split ( ',' ) . length ) ] : 路参IP ;
1773+ 启用反代兜底 = false ;
1774+ return ;
1775+ }
17181776 }
1777+ // query 中的 ?socks5= 和 ?http= 已在初始化时由 searchParams.get 处理
17191778
1720- // 处理SOCKS5/HTTP代理参数
1721- let socksMatch ;
1722- if ( ( socksMatch = pathname . match ( / \/ ( s o c k s 5 ? | h t t p ) : \/ ? \/ ? ( [ ^ / ? # ] + ) / i) ) ) {
1723- // 格式: /socks5://... 或 /http://...
1779+ // ==================== 第二步:处理路径中的 SOCKS5/HTTP 协议关键词 ====================
1780+ // 匹配:/socks5://..., /socks://.., /http://...
1781+ else if ( ( socksMatch = pathname . match ( / \/ ( s o c k s 5 ? | h t t p ) : \/ ? \/ ? ( [ ^ / ? # \s ] + ) / i) ) ) {
17241782 启用SOCKS5反代 = socksMatch [ 1 ] . toLowerCase ( ) === 'http' ? 'http' : 'socks5' ;
1725- 我的SOCKS5账号 = socksMatch [ 2 ] ;
1783+ 我的SOCKS5账号 = socksMatch [ 2 ] . split ( '/' ) [ 0 ] ;
17261784 启用SOCKS5全局反代 = true ;
1727-
1728- // 处理Base64编码的用户名密码
1729- if ( 我的SOCKS5账号 . includes ( '@' ) ) {
1730- const atIndex = 我的SOCKS5账号 . lastIndexOf ( '@' ) ;
1731- let userPassword = 我的SOCKS5账号 . substring ( 0 , atIndex ) . replaceAll ( '%3D' , '=' ) ;
1732- if ( / ^ (?: [ A - Z 0 - 9 + / ] { 4 } ) * (?: [ A - Z 0 - 9 + / ] { 2 } = = | [ A - Z 0 - 9 + / ] { 3 } = ) ? $ / i. test ( userPassword ) && ! userPassword . includes ( ':' ) ) {
1733- userPassword = atob ( userPassword ) ;
1734- }
1735- 我的SOCKS5账号 = `${ userPassword } @${ 我的SOCKS5账号 . substring ( atIndex + 1 ) } ` ;
1736- }
1737- } else if ( ( socksMatch = pathname . match ( / \/ ( g ? s 5 | s o c k s 5 | g ? h t t p ) = ( [ ^ / ? # ] + ) / i) ) ) {
1738- // 格式: /socks5=... 或 /s5=... 或 /gs5=... 或 /http=... 或 /ghttp=...
1785+ }
1786+ // 匹配:/socks5=..., /s5=..., /gs5=..., /http=..., /ghttp=...
1787+ else if ( ( socksMatch = pathname . match ( / \/ ( g ? s 5 | s o c k s 5 | g ? h t t p ) = ( [ ^ / ? # \s ] + ) / i) ) ) {
17391788 const type = socksMatch [ 1 ] . toLowerCase ( ) ;
1740- 我的SOCKS5账号 = socksMatch [ 2 ] ;
1789+ 我的SOCKS5账号 = socksMatch [ 2 ] . split ( '/' ) [ 0 ] ;
17411790 启用SOCKS5反代 = type . includes ( 'http' ) ? 'http' : 'socks5' ;
1742- 启用SOCKS5全局反代 = type . startsWith ( 'g' ) || 启用SOCKS5全局反代 ; // gs5 或 ghttp 开头启用全局
1791+ 启用SOCKS5全局反代 = type . startsWith ( 'g' ) || 启用SOCKS5全局反代 ;
1792+ }
1793+
1794+ // ==================== 第三步:处理路径中的 proxyip/pyip/ip ====================
1795+ else if ( ( proxyMatch = pathLower . match ( / \/ ( p r o x y i p [ . = ] | p y i p = | i p = ) ( [ ^ ? # \s ] + ) / ) ) ) {
1796+ let 路参IP = 提取路径值 ( proxyMatch [ 2 ] ) ;
1797+ // proxyip 值以 socks5:// 或 http:// 开头,视为对应协议处理
1798+ if ( ! 解析代理URL ( 路参IP ) ) {
1799+ // 否则作为 IP 反代
1800+ 反代IP = 路参IP . includes ( ',' ) ? 路参IP . split ( ',' ) [ Math . floor ( Math . random ( ) * 路参IP . split ( ',' ) . length ) ] : 路参IP ;
1801+ 启用反代兜底 = false ;
1802+ return ;
1803+ }
17431804 }
17441805
1745- // 解析SOCKS5地址
1806+ // 统一解析SOCKS5地址
17461807 if ( 我的SOCKS5账号 ) {
17471808 try {
17481809 parsedSocks5Address = await 获取SOCKS5账号 ( 我的SOCKS5账号 ) ;
1749- 启用SOCKS5反代 = searchParams . get ( 'http' ) ? 'http' : 启用SOCKS5反代 ;
1810+ 启用SOCKS5反代 = searchParams . get ( 'http' ) ? 'http' : ( 启用SOCKS5反代 || 'socks5' ) ;
17501811 } catch ( err ) {
17511812 console . error ( '解析SOCKS5地址失败:' , err . message ) ;
17521813 启用SOCKS5反代 = null ;
0 commit comments