hodlbod on Nostr: Yeah, the tricky part seems to be intercepting send messages so that you can buffer ...
Yeah, the tricky part seems to be intercepting send messages so that you can buffer them and re-send after authentication (or remove reqs that have been closed before they were sent while you were waiting for auth). Here's my (half-baked) policy for that:
```
export const socketPolicyDeferOnAuth = (socket: Socket) => {
const send$ = socket.send$
const buffer: ClientMessage[] = []
const authState = new AuthState(socket)
const okStatuses = [AuthStatus.None, AuthStatus.Ok]
// Defer sending certain messages when we're not authenticated
socket.send$ = send$.pipe(
filter(message => {
// Always allow sending auth
if (isClientAuth(message)) return true
// Always allow sending join requests
if (isClientEvent(message) && message[1].kind === AUTH_JOIN) return true
// If we're not ok, remove the message and save it for later
if (!okStatuses.includes(authState.status)) {
buffer.push(message)
return false
}
return true
}),
)
// Send buffered messages when we get successful auth
return authState.subscribe((status: AuthStatus) => {
if (okStatuses.includes(status)) {
const reqs = new Set(buffer.filter(isClientReq).map(nth(1)))
const closed = new Set(buffer.filter(isClientClose).map(nth(1)))
for (const message of buffer.splice(0)) {
// Skip requests that were closed before they were sent
if (isClientReq(message) && closed.has(message[1])) continue
// Skip closes for requests that were never sent
if (isClientClose(message) && reqs.has(message[1])) continue
socket.send(message)
}
}
})
}
```
Published at
2025-03-26 21:01:13Event JSON
{
"id": "78e69a3443a73dcf03e4a3db077f409c8793aaf229ae98aba2c67c966b761c95",
"pubkey": "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322",
"created_at": 1743022873,
"kind": 1,
"tags": [
[
"p",
"c6603b0f1ccfec625d9c08b753e4f774eaf7d1cf2769223125b5fd4da728019e",
"wss://relay.mostr.pub/",
"Cesar Dias"
],
[
"e",
"7232af889e79b07bc8dab1307acc24766bd869f9a9be3ff86f8239be532ef2f9",
"wss://127.0.0.1:4869/",
"root"
],
[
"e",
"901fcdbad7588d2527898d62688abeaf3d4801964f9cf3775b17947be799b068",
"wss://relay.damus.io",
"mention"
],
[
"e",
"3ab7159fc3a3f4d7af80615e4a988d32cdd212980c7057a514b4cfdc991aa1d1",
"wss://nos.lol/",
"reply",
"c6603b0f1ccfec625d9c08b753e4f774eaf7d1cf2769223125b5fd4da728019e"
],
[
"client",
"Coracle",
"31990:97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322:1685968093690"
]
],
"content": "Yeah, the tricky part seems to be intercepting send messages so that you can buffer them and re-send after authentication (or remove reqs that have been closed before they were sent while you were waiting for auth). Here's my (half-baked) policy for that:\n\n```\nexport const socketPolicyDeferOnAuth = (socket: Socket) =\u003e {\n const send$ = socket.send$\n const buffer: ClientMessage[] = []\n const authState = new AuthState(socket)\n const okStatuses = [AuthStatus.None, AuthStatus.Ok]\n // Defer sending certain messages when we're not authenticated\n socket.send$ = send$.pipe(\n filter(message =\u003e {\n // Always allow sending auth\n if (isClientAuth(message)) return true\n // Always allow sending join requests\n if (isClientEvent(message) \u0026\u0026 message[1].kind === AUTH_JOIN) return true\n // If we're not ok, remove the message and save it for later\n if (!okStatuses.includes(authState.status)) {\n buffer.push(message)\n return false\n }\n return true\n }),\n )\n // Send buffered messages when we get successful auth\n return authState.subscribe((status: AuthStatus) =\u003e {\n if (okStatuses.includes(status)) {\n const reqs = new Set(buffer.filter(isClientReq).map(nth(1)))\n const closed = new Set(buffer.filter(isClientClose).map(nth(1)))\n for (const message of buffer.splice(0)) {\n // Skip requests that were closed before they were sent\n if (isClientReq(message) \u0026\u0026 closed.has(message[1])) continue\n // Skip closes for requests that were never sent\n if (isClientClose(message) \u0026\u0026 reqs.has(message[1])) continue\n socket.send(message)\n }\n }\n })\n}\n```",
"sig": "b4a6eaa61456a5d17b8d96f7088116bc6ecc98c3ed71213938c2ee0c45f0ee550671ae2898bb80877344fd6858be45afb0c7a50e80de2be9e350242f98d6863d"
}