Skip to content

Commit

Permalink
rewrite url selection for launch ui
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-bonez committed Jan 21, 2025
1 parent 720b4a2 commit 9c91379
Showing 1 changed file with 123 additions and 32 deletions.
155 changes: 123 additions & 32 deletions web/projects/ui/src/app/services/config.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class ConfigService {
isLocalhost(): boolean {
return useMocks
? mocks.maskAs === 'localhost'
: this.hostname === 'localhost'
: this.hostname === 'localhost' || this.hostname === '127.0.0.1'
}

isIpv4(): boolean {
Expand All @@ -52,6 +52,18 @@ export class ConfigService {
: new RegExp(utils.Patterns.ipv4.regex).test(this.hostname)
}

isLanIpv4(): boolean {
return useMocks
? mocks.maskAs === 'ipv4'
: new RegExp(utils.Patterns.ipv4.regex).test(this.hostname) &&
(this.hostname.startsWith('192.168.') ||
this.hostname.startsWith('10.') ||
(this.hostname.startsWith('172.') &&
!![this.hostname.split('.').map(Number)[1]].filter(
n => n >= 16 && n < 32,
).length))
}

isIpv6(): boolean {
return useMocks
? mocks.maskAs === 'ipv6'
Expand All @@ -69,7 +81,7 @@ export class ConfigService {
!this.isTor() &&
!this.isLocal() &&
!this.isLocalhost() &&
!this.isIpv4() &&
!this.isLanIpv4() &&
!this.isIpv6()
}

Expand All @@ -91,7 +103,7 @@ export class ConfigService {
/** ${scheme}://${username}@${host}:${externalPort}${suffix} */
launchableAddress(
interfaces: PackageDataEntry['serviceInterfaces'],
hosts: PackageDataEntry['hosts'],
hosts: T.Hosts,
): string {
const ui = Object.values(interfaces).find(
i =>
Expand All @@ -106,39 +118,117 @@ export class ConfigService {

if (!host) return ''

const hostnameInfo = host.hostnameInfo[ui.addressInfo.internalPort]
let hostnameInfo = host.hostnameInfo[ui.addressInfo.internalPort]
hostnameInfo = hostnameInfo.filter(
h =>
this.isLocalhost() ||
h.kind !== 'ip' ||
h.hostname.kind !== 'ipv6' ||
!h.hostname.value.startsWith('fe80::'),
)
if (this.isLocalhost()) {
const local = hostnameInfo.find(
h => h.kind === 'ip' && h.hostname.kind === 'local',
)
if (local) {
hostnameInfo.unshift({
kind: 'ip',
networkInterfaceId: 'lo',
public: false,
hostname: {
kind: 'local',
port: local.hostname.port,
sslPort: local.hostname.sslPort,
value: 'localhost',
},
})
}
}

if (!hostnameInfo) return ''

const addressInfo = ui.addressInfo
const scheme = this.isHttps()
? ui.addressInfo.sslScheme === 'https'
? 'https'
: 'http'
: ui.addressInfo.scheme === 'http'
? 'http'
: 'https'
const username = addressInfo.username ? addressInfo.username + '@' : ''
const suffix = addressInfo.suffix || ''
const url = new URL(`${scheme}://${username}placeholder${suffix}`)
const url = new URL(`https://${username}placeholder${suffix}`)
const use = (hostname: {
value: string
port: number | null
sslPort: number | null
}) => {
url.hostname = hostname.value
const useSsl =
hostname.port && hostname.sslPort ? this.isHttps() : !!hostname.sslPort
url.protocol = useSsl
? `${addressInfo.sslScheme || 'https'}:`
: `${addressInfo.scheme || 'http'}:`
const port = useSsl ? hostname.sslPort : hostname.port
const omitPort = useSsl
? ui.addressInfo.sslScheme === 'https' && port === 443
: ui.addressInfo.scheme === 'http' && port === 80
if (!omitPort && port) url.port = String(port)
}
const useFirst = (
hostnames: (
| {
value: string
port: number | null
sslPort: number | null
}
| undefined
)[],
) => {
const first = hostnames.find(h => h)
if (first) {
use(first)
}
return !!first
}

const ipHostnames = hostnameInfo
.filter(h => h.kind === 'ip')
.map(h => h.hostname) as T.IpHostname[]
const domainHostname = ipHostnames.find(h => h.kind === 'domain') as {
kind: 'domain'
domain: string
subdomain: string | null
port: number | null
sslPort: number | null
}
const onionHostname = hostnameInfo.find(h => h.kind === 'onion')
?.hostname as T.OnionHostname | undefined
const domainHostname = ipHostnames
.filter(h => h.kind === 'domain')
.map(h => h as T.IpHostname & { kind: 'domain' })
.map(h => ({
value: h.domain,
sslPort: h.sslPort,
port: h.port,
}))[0]
const wanIpHostname = hostnameInfo
.filter(h => h.kind === 'ip' && h.public && h.hostname.kind !== 'domain')
.map(h => h.hostname as Exclude<T.IpHostname, { kind: 'domain' }>)
.map(h => ({
value: h.value,
sslPort: h.sslPort,
port: h.port,
}))[0]
const onionHostname = hostnameInfo
.filter(h => h.kind === 'onion')
.map(h => h as T.HostnameInfo & { kind: 'onion' })
.map(h => ({
value: h.hostname.value,
sslPort: h.hostname.sslPort,
port: h.hostname.port,
}))[0]
const localHostname = ipHostnames
.filter(h => h.kind === 'local')
.map(h => h as T.IpHostname & { kind: 'local' })
.map(h => ({ value: h.value, sslPort: h.sslPort, port: h.port }))[0]

if (this.isClearnet() && domainHostname) {
url.hostname = domainHostname.domain
} else if (this.isTor() && onionHostname) {
url.hostname = onionHostname.value
if (this.isClearnet()) {
if (
!useFirst([domainHostname, wanIpHostname, onionHostname, localHostname])
) {
return ''
}
} else if (this.isTor()) {
if (
!useFirst([onionHostname, domainHostname, wanIpHostname, localHostname])
) {
return ''
}
} else if (this.isIpv6()) {
const ipv6Hostname = ipHostnames.find(h => h.kind === 'ipv6') as {
kind: 'ipv6'
Expand All @@ -148,18 +238,19 @@ export class ConfigService {
sslPort: number | null
}

if (!ipv6Hostname) return ''

url.hostname = ipv6Hostname.value
url.port = String(ipv6Hostname.sslPort || ipv6Hostname.port)
if (!useFirst([ipv6Hostname, localHostname])) {
return ''
}
} else {
// ipv4 or .local or localhost
const localHostname = ipHostnames.find(h => h.kind === 'local')

if (!localHostname) return ''

url.hostname = this.hostname
url.port = String(localHostname.sslPort || localHostname.port)
use({
value: this.hostname,
port: localHostname.port,
sslPort: localHostname.sslPort,
})
}

return url.href
Expand Down

0 comments on commit 9c91379

Please sign in to comment.