• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cameri / nostream / 25601018106

09 May 2026 12:22PM UTC coverage: 33.99% (-31.1%) from 65.107%
25601018106

Pull #615

github

web-flow
Merge 1ef509ec3 into 36e5af87e
Pull Request #615: test: add unit tests for remaining app workers (#489)

788 of 3170 branches covered (24.86%)

Branch coverage included in aggregate %.

0 of 8 new or added lines in 2 files covered. (0.0%)

1822 existing lines in 87 files now uncovered.

2352 of 6068 relevant lines covered (38.76%)

13.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.45
/src/utils/http.ts
1
import { IncomingMessage } from 'http'
2

3
import { createLogger } from '../factories/logger-factory'
1✔
4
import { Settings } from '../@types/settings'
5

6
const logger = createLogger('http-utils')
1✔
7

8
const normalizeIpAddress = (input: string): string => {
1✔
9
  if (input.startsWith('::ffff:')) {
976✔
10
    return input.slice(7)
244✔
11
  }
12

13
  return input
732✔
14
}
15

16
const isTrustedProxy = (ipAddress: string, settings: Settings): boolean => {
1✔
17
  const trustedProxies = settings.network?.trustedProxies
244✔
18

19
  if (!Array.isArray(trustedProxies) || trustedProxies.length === 0) {
244!
UNCOV
20
    return false
×
21
  }
22

23
  const normalizedRemote = normalizeIpAddress(ipAddress)
244✔
24

25
  return trustedProxies.some((trustedProxy) => {
244✔
26
    return normalizeIpAddress(trustedProxy) === normalizedRemote
732✔
27
  })
28
}
29

30
export const getRemoteAddress = (request: IncomingMessage, settings: Settings): string => {
1✔
31
  let header: string | undefined
32
  // TODO: Remove deprecation warning
33
  if ('network' in settings && 'remote_ip_header' in settings.network) {
235!
UNCOV
34
    logger.warn(`WARNING: Setting network.remote_ip_header is deprecated and will be removed in a future version.
×
35
        Use network.remoteIpHeader instead.`)
UNCOV
36
    header = settings.network['remote_ip_header'] as string
×
37
  } else {
38
    header = settings.network.remoteIpHeader as string
235✔
39
  }
40

41
  const trustedProxies = settings.network?.trustedProxies
235✔
42
  if (header && (!Array.isArray(trustedProxies) || trustedProxies.length === 0)) {
235!
UNCOV
43
    logger.warn('WARNING: network.remoteIpHeader is set but network.trustedProxies is empty. Forwarded headers will be ignored. Add your proxy IP to network.trustedProxies.')
×
44
  }
45

46
  const rawHeaderAddress = header ? request.headers[header] : undefined
235!
47
  const headerAddress = Array.isArray(rawHeaderAddress) ? rawHeaderAddress[0] : rawHeaderAddress
235!
48
  const socketAddress = request.socket.remoteAddress
235✔
49

50
  const trustedProxy = typeof socketAddress === 'string'
235✔
51
    && isTrustedProxy(socketAddress, settings)
52

53
  const result = trustedProxy && typeof headerAddress === 'string'
235!
54
    ? headerAddress
55
    : socketAddress
56

57
  return (result as string).split(',')[0].trim()
235✔
58
}
59

60
const normalizePathPrefix = (pathPrefix: string | undefined): string => {
1✔
61
  if (typeof pathPrefix !== 'string') {
18✔
62
    return ''
9✔
63
  }
64

65
  const prefix = pathPrefix.split(',')[0].trim()
9✔
66

67
  if (!prefix.startsWith('/') || prefix.startsWith('//')) {
9!
UNCOV
68
    return ''
×
69
  }
70

71
  try {
9✔
72
    const { pathname } = new URL(prefix, 'http://nostream.local')
9✔
73
    const normalized = pathname.replace(/\/+$/, '')
9✔
74

75
    return normalized === '/' ? '' : normalized
9!
76
  } catch {
77
    return ''
×
78
  }
79
}
80

81
const getRelayUrlPathPrefix = (relayUrl: string | undefined): string => {
1✔
82
  if (typeof relayUrl !== 'string') {
9!
UNCOV
83
    return ''
×
84
  }
85

86
  try {
9✔
87
    return normalizePathPrefix(new URL(relayUrl).pathname)
9✔
88
  } catch {
89
    return ''
×
90
  }
91
}
92

93
const getTrustedForwardedPathPrefix = (request: IncomingMessage, settings: Settings): string => {
1✔
94
  const socketAddress = request.socket?.remoteAddress
9✔
95
  if (typeof socketAddress !== 'string' || !isTrustedProxy(socketAddress, settings)) {
9!
UNCOV
96
    return ''
×
97
  }
98

99
  const rawHeader = request.headers?.['x-forwarded-prefix']
9✔
100
  const rawPrefix = Array.isArray(rawHeader) ? rawHeader[0] : rawHeader
9!
101

102
  return normalizePathPrefix(rawPrefix)
9✔
103
}
104

105
export const getPublicPathPrefix = (request: IncomingMessage, settings: Settings): string => {
1✔
106
  return getTrustedForwardedPathPrefix(request, settings) || getRelayUrlPathPrefix(settings.info?.relay_url)
9✔
107
}
108

109
export const joinPathPrefix = (prefix: string, path: string): string => {
1✔
110
  const normalizedPrefix = prefix.replace(/\/+$/, '')
5✔
111
  const normalizedPath = path.startsWith('/') ? path : `/${path}`
5!
112

113
  return `${normalizedPrefix}${normalizedPath}`
5✔
114
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc