Skip to content

Commit

Permalink
Improved web socket user connect handling
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianRappl committed Dec 18, 2024
1 parent 3478424 commit 508757b
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 30 deletions.
4 changes: 2 additions & 2 deletions docs/script-injector.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ interface Script {
| undefined;
setup?(ctx: ScriptContextData): void;
teardown?(ctx: ScriptContextData): void;
connected?(ctx: ScriptContextData, e: KrasWebSocketEvent): void;
connected?(ctx: ScriptContextData, e: KrasWebSocketEvent): void | boolean;
disconnected?(ctx: ScriptContextData, e: KrasWebSocketEvent): void;
}
```
Expand Down Expand Up @@ -208,6 +208,6 @@ export interface KrasAnswer {
}
```

This allows also specifying `connected` and `disconnected` functions to handle WebSocket connections.
This allows also specifying `connected` and `disconnected` functions to handle WebSocket connections. If `connected` returns a truthy value then other scripts won't be bothered with `connected`.

The `setup` and `teardown` functions are used to properly initialize or dispose relevant resources. They are called when the script is first discovered or removed / replaced, e.g., in case of a file change.
40 changes: 21 additions & 19 deletions src/server/injectors/proxy-injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,27 @@ export default class ProxyInjector implements KrasInjector {
this.core = core;

core.on('user-connected', (e: KrasWebSocketEvent) => {
const [target] = this.connectors.filter((m) => m.target === e.target);

if (target) {
const { id, ws, req } = e;
const url = target.address + e.url;
const details = {
headers: req.headers,
remoteAddress: req.connection.remoteAddress || req.socket.remoteAddress,
port: getPort(req),
encrypted: isEncrypted(req),
};
const headers = this.makeHeaders(details, 'ws');
this.sessions[e.id] = proxyWebSocket({
id,
ws,
headers,
url,
core,
});
if (!e.handled) {
const [target] = this.connectors.filter((m) => m.target === e.target);

if (target) {
const { id, ws, req } = e;
const url = target.address + e.url;
const details = {
headers: req.headers,
remoteAddress: req.connection.remoteAddress || req.socket.remoteAddress,
port: getPort(req),
encrypted: isEncrypted(req),
};
const headers = this.makeHeaders(details, 'ws');
this.sessions[e.id] = proxyWebSocket({
id,
ws,
headers,
url,
core,
});
}
}
});

Expand Down
23 changes: 14 additions & 9 deletions src/server/injectors/script-injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export interface ScriptExports {
): KrasAnswer | Promise<KrasAnswer> | undefined;
setup?(ctx: ScriptContextData): void;
teardown?(ctx: ScriptContextData): void;
connected?(ctx: ScriptContextData, e: KrasWebSocketEvent): void;
connected?(ctx: ScriptContextData, e: KrasWebSocketEvent): void | boolean;
disconnected?(ctx: ScriptContextData, e: KrasWebSocketEvent): void;
}

Expand Down Expand Up @@ -99,14 +99,19 @@ export default class ScriptInjector implements KrasInjector {
});

core.on('user-connected', (e: KrasWebSocketEvent) => {
for (const { handler } of this.files) {
if (handler && typeof handler.connected === 'function') {
const ctx = this.getContext();

try {
handler.connected(ctx, e);
} catch (err) {
core.emit('error', err);
if (!e.handled) {
for (const { handler } of this.files) {
if (handler && typeof handler.connected === 'function') {
const ctx = this.getContext();

try {
if (handler.connected(ctx, e)) {
e.handled = true;
break;
}
} catch (err) {
core.emit('error', err);
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/server/types/kras-express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ export interface KrasWebSocketEvent {
target: string;
url: string;
req: Request;
handled?: boolean;
}

0 comments on commit 508757b

Please sign in to comment.