import { decodeAndTrim, getIfNotBlank, parseBoolOrPresence, parsePortOrDefault, parseQueryStringNormalized, parseUrlLike, safeDecodeURIComponent, stripUriScheme, } from './helpers' export function URI_Trojan(line: string): IProxyTrojanConfig { const afterScheme = stripUriScheme(line, 'trojan', 'Invalid trojan uri') if (!afterScheme) { throw new Error('Invalid trojan uri') } const { auth: passwordRaw, host: server, port, query: addons, fragment: nameRaw, } = parseUrlLike(afterScheme, { requireAuth: true, errorMessage: 'Invalid trojan uri', }) const portNum = parsePortOrDefault(port, 443) const password = safeDecodeURIComponent(passwordRaw) ?? passwordRaw const name = decodeAndTrim(nameRaw) ?? `Trojan ${server}:${portNum}` const proxy: IProxyTrojanConfig = { type: 'trojan', name, server, port: portNum, password, } const params = parseQueryStringNormalized(addons) const network = params.type if (network && ['ws', 'grpc', 'h2', 'tcp'].includes(network)) { proxy.network = network as NetworkType } const host = getIfNotBlank(params.host) const path = getIfNotBlank(params.path) if (params.alpn) { proxy.alpn = params.alpn.split(',') } if (params.sni) { proxy.sni = params.sni } if (Object.prototype.hasOwnProperty.call(params, 'skip-cert-verify')) { proxy['skip-cert-verify'] = parseBoolOrPresence(params['skip-cert-verify']) } proxy.fingerprint = params.fingerprint ?? params.fp if (params.encryption) { const encryption = params.encryption.split(';') if (encryption.length === 3) { proxy['ss-opts'] = { enabled: true, method: encryption[1], password: encryption[2], } } } if (params['client-fingerprint']) { proxy['client-fingerprint'] = params[ 'client-fingerprint' ] as ClientFingerprint } if (proxy.network === 'ws') { const wsOpts: WsOptions = {} if (host) wsOpts.headers = { Host: host } if (path) wsOpts.path = path if (Object.keys(wsOpts).length > 0) { proxy['ws-opts'] = wsOpts } } else if (proxy.network === 'grpc') { const serviceName = getIfNotBlank(path) if (serviceName) { proxy['grpc-opts'] = { 'grpc-service-name': serviceName } } } return proxy }