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

cameri / nostream / 26382712021

25 May 2026 04:09AM UTC coverage: 62.715% (-2.4%) from 65.119%
26382712021

Pull #627

github

web-flow
Merge 96e29866f into 54139ed49
Pull Request #627: test(integration): verify response content-types across HTTP routes

1757 of 3168 branches covered (55.46%)

Branch coverage included in aggregate %.

4036 of 6069 relevant lines covered (66.5%)

7.99 hits per line

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

91.04
/src/adapters/web-socket-server-adapter.ts
1
import { IncomingMessage, Server } from 'http'
2
import WebSocket, { OPEN, WebSocketServer } from 'ws'
1✔
3
import { propEq } from 'ramda'
1✔
4

5
import { IWebSocketAdapter, IWebSocketServerAdapter } from '../@types/adapters'
6
import { WebSocketAdapterEvent, WebSocketServerAdapterEvent } from '../constants/adapter'
1✔
7
import { createLogger } from '../factories/logger-factory'
1✔
8
import { Event } from '../@types/event'
9
import { Factory } from '../@types/base'
10
import { getRemoteAddress } from '../utils/http'
1✔
11
import { isRateLimited } from '../handlers/request-handlers/rate-limiter-middleware'
1✔
12
import { Settings } from '../@types/settings'
13
import { WebServerAdapter } from './web-server-adapter'
1✔
14

15
const logger = createLogger('web-socket-server-adapter')
1✔
16

17
const WSS_CLIENT_HEALTH_PROBE_INTERVAL = 120000
1✔
18

19
export class WebSocketServerAdapter extends WebServerAdapter implements IWebSocketServerAdapter {
1✔
20
  private webSocketsAdapters: WeakMap<WebSocket, IWebSocketAdapter>
21

22
  private heartbeatInterval: NodeJS.Timeout
23

24
  public constructor(
25
    webServer: Server,
26
    private readonly webSocketServer: WebSocketServer,
16✔
27
    private readonly createWebSocketAdapter: Factory<
16✔
28
      IWebSocketAdapter,
29
      [WebSocket, IncomingMessage, IWebSocketServerAdapter]
30
    >,
31
    private readonly settings: () => Settings,
16✔
32
  ) {
33
    logger('created')
16✔
34
    super(webServer)
16✔
35

36
    this.webSocketsAdapters = new WeakMap()
16✔
37

38
    this.on(WebSocketServerAdapterEvent.Broadcast, this.onBroadcast.bind(this))
16✔
39

40
    this.webSocketServer
16✔
41
      .on(WebSocketServerAdapterEvent.Connection, this.onConnection.bind(this))
42
      .on('error', (error) => {
43
        logger('error: %o', error)
×
44
      })
45
    this.heartbeatInterval = setInterval(this.onHeartbeat.bind(this), WSS_CLIENT_HEALTH_PROBE_INTERVAL)
16✔
46
  }
47

48
  public close(callback?: () => void): void {
49
    super.close(() => {
21✔
50
      logger('closing')
20✔
51
      clearInterval(this.heartbeatInterval)
20✔
52
      this.webSocketServer.clients.forEach((webSocket: WebSocket) => {
20✔
53
        const webSocketAdapter = this.webSocketsAdapters.get(webSocket)
2✔
54
        if (webSocketAdapter) {
2!
55
          logger('terminating client %s: %s', webSocketAdapter.getClientId(), webSocketAdapter.getClientAddress())
×
56
        }
57
        webSocket.terminate()
2✔
58
      })
59
      logger('closing web socket server')
20✔
60
      this.webSocketServer.close(() => {
20✔
61
        this.webSocketServer.removeAllListeners()
20✔
62
        if (typeof callback !== 'undefined') {
20✔
63
          callback()
2✔
64
        }
65
        logger('closed')
20✔
66
      })
67
    })
68
    this.removeAllListeners()
21✔
69
  }
70

71
  private onBroadcast(event: Event) {
72
    this.webSocketServer.clients.forEach((webSocket: WebSocket) => {
2✔
73
      if (!propEq('readyState', OPEN)(webSocket)) {
2✔
74
        return
1✔
75
      }
76
      const webSocketAdapter = this.webSocketsAdapters.get(webSocket) as IWebSocketAdapter
1✔
77
      if (!webSocketAdapter) {
1!
78
        return
×
79
      }
80
      webSocketAdapter.emit(WebSocketAdapterEvent.Event, event)
1✔
81
    })
82
  }
83

84
  public getConnectedClients(): number {
85
    return Array.from(this.webSocketServer.clients).filter(propEq('readyState', OPEN)).length
2✔
86
  }
87

88
  private async onConnection(client: WebSocket, req: IncomingMessage) {
89
    const currentSettings = this.settings()
4✔
90
    const remoteAddress = getRemoteAddress(req, currentSettings)
4✔
91

92
    logger('client %s connected: %o', remoteAddress, req.headers)
4✔
93

94
    if (await isRateLimited(remoteAddress, currentSettings)) {
4✔
95
      logger('client %s terminated: rate-limited', remoteAddress)
1✔
96
      client.terminate()
1✔
97
      return
1✔
98
    }
99

100
    this.webSocketsAdapters.set(client, this.createWebSocketAdapter([client, req, this]))
3✔
101
  }
102

103
  private onHeartbeat() {
104
    this.webSocketServer.clients.forEach((webSocket) => {
1✔
105
      const webSocketAdapter = this.webSocketsAdapters.get(webSocket) as IWebSocketAdapter
1✔
106
      if (webSocketAdapter) {
1!
107
        webSocketAdapter.emit(WebSocketAdapterEvent.Heartbeat)
1✔
108
      }
109
    })
110
  }
111
}
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