mirror of
https://github.com/LukeHagar/crossws.git
synced 2025-12-06 04:19:26 +00:00
feat: auto generated peer id
This commit is contained in:
@@ -17,9 +17,13 @@ Websocket [hooks](/guide/hooks) accept a peer instance as their first argument.
|
|||||||
|
|
||||||
Send a message to the connected client
|
Send a message to the connected client
|
||||||
|
|
||||||
|
### `peer.addr`
|
||||||
|
|
||||||
|
The peer address (might be `undefined`)
|
||||||
|
|
||||||
### `peer.id`
|
### `peer.id`
|
||||||
|
|
||||||
The peer address or unique id (might be `undefined`)
|
A unique id assigned to the peer.
|
||||||
|
|
||||||
### `peer.readyState`
|
### `peer.readyState`
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ export const websocket = {
|
|||||||
hooks: defineHooks({
|
hooks: defineHooks({
|
||||||
open(peer) {
|
open(peer) {
|
||||||
console.log("[ws] open", peer);
|
console.log("[ws] open", peer);
|
||||||
peer.send({ user: "system", message: `Welcome ${peer}!` });
|
peer.send({ user: "server", message: `Welcome ${peer}!` });
|
||||||
},
|
},
|
||||||
|
|
||||||
message(peer, message) {
|
message(peer, message) {
|
||||||
console.log("[ws] message", peer, message);
|
console.log("[ws] message", peer, message);
|
||||||
if (message.text().includes("ping")) {
|
if (message.text().includes("ping")) {
|
||||||
peer.send({ user: "system", message: "pong" });
|
peer.send({ user: "server", message: "pong" });
|
||||||
} else {
|
} else {
|
||||||
peer.send({ user: peer.toString(), message: message.toString() });
|
peer.send({ user: peer.toString(), message: message.toString() });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,12 +64,12 @@
|
|||||||
const isSecure = location.protocol === "https:";
|
const isSecure = location.protocol === "https:";
|
||||||
const url = (isSecure ? "wss://" : "ws://") + location.host + "/_ws";
|
const url = (isSecure ? "wss://" : "ws://") + location.host + "/_ws";
|
||||||
if (ws) {
|
if (ws) {
|
||||||
log("system", "Closing previous connection before reconnecting...");
|
log("ws", "Closing previous connection before reconnecting...");
|
||||||
ws.close();
|
ws.close();
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
log("system", "Connecting to", url, "...");
|
log("ws", "Connecting to", url, "...");
|
||||||
ws = new WebSocket(url);
|
ws = new WebSocket(url);
|
||||||
|
|
||||||
ws.addEventListener("message", (event) => {
|
ws.addEventListener("message", (event) => {
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
await new Promise((resolve) => ws.addEventListener("open", resolve));
|
await new Promise((resolve) => ws.addEventListener("open", resolve));
|
||||||
log("system", "Connected!");
|
log("ws", "Connected!");
|
||||||
};
|
};
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ping = () => {
|
const ping = () => {
|
||||||
log("you", "Sending ping");
|
log("ws", "Sending ping");
|
||||||
ws.send("ping");
|
ws.send("ping");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,7 +114,6 @@
|
|||||||
}).mount();
|
}).mount();
|
||||||
|
|
||||||
await connect();
|
await connect();
|
||||||
ping();
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="h-screen flex flex-col justify-between">
|
<body class="h-screen flex flex-col justify-between">
|
||||||
@@ -126,7 +125,7 @@
|
|||||||
<p class="text-gray-500 mb-1 text-xs ml-10">{{ message.user }}</p>
|
<p class="text-gray-500 mb-1 text-xs ml-10">{{ message.user }}</p>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img
|
<img
|
||||||
:src="'https://www.gravatar.com/avatar/' + (message.user + rand) + '?s=512&d=monsterid'"
|
:src="'https://www.gravatar.com/avatar/' + encodeURIComponent(message.user + rand) + '?s=512&d=monsterid'"
|
||||||
alt="Avatar"
|
alt="Avatar"
|
||||||
class="w-8 h-8 rounded-full"
|
class="w-8 h-8 rounded-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -65,12 +65,12 @@ export default /* html */ `
|
|||||||
const isSecure = location.protocol === "https:";
|
const isSecure = location.protocol === "https:";
|
||||||
const url = (isSecure ? "wss://" : "ws://") + location.host + "/_ws";
|
const url = (isSecure ? "wss://" : "ws://") + location.host + "/_ws";
|
||||||
if (ws) {
|
if (ws) {
|
||||||
log("system", "Closing previous connection before reconnecting...");
|
log("ws", "Closing previous connection before reconnecting...");
|
||||||
ws.close();
|
ws.close();
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
log("system", "Connecting to", url, "...");
|
log("ws", "Connecting to", url, "...");
|
||||||
ws = new WebSocket(url);
|
ws = new WebSocket(url);
|
||||||
|
|
||||||
ws.addEventListener("message", (event) => {
|
ws.addEventListener("message", (event) => {
|
||||||
@@ -84,7 +84,7 @@ export default /* html */ `
|
|||||||
});
|
});
|
||||||
|
|
||||||
await new Promise((resolve) => ws.addEventListener("open", resolve));
|
await new Promise((resolve) => ws.addEventListener("open", resolve));
|
||||||
log("system", "Connected!");
|
log("ws", "Connected!");
|
||||||
};
|
};
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
@@ -101,7 +101,7 @@ export default /* html */ `
|
|||||||
};
|
};
|
||||||
|
|
||||||
const ping = () => {
|
const ping = () => {
|
||||||
log("you", "Sending ping");
|
log("ws", "Sending ping");
|
||||||
ws.send("ping");
|
ws.send("ping");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,7 +115,6 @@ export default /* html */ `
|
|||||||
}).mount();
|
}).mount();
|
||||||
|
|
||||||
await connect();
|
await connect();
|
||||||
ping();
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="h-screen flex flex-col justify-between">
|
<body class="h-screen flex flex-col justify-between">
|
||||||
@@ -127,7 +126,7 @@ export default /* html */ `
|
|||||||
<p class="text-gray-500 mb-1 text-xs ml-10">{{ message.user }}</p>
|
<p class="text-gray-500 mb-1 text-xs ml-10">{{ message.user }}</p>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img
|
<img
|
||||||
:src="'https://www.gravatar.com/avatar/' + (message.user + rand) + '?s=512&d=monsterid'"
|
:src="'https://www.gravatar.com/avatar/' + encodeURIComponent(message.user + rand) + '?s=512&d=monsterid'"
|
||||||
alt="Avatar"
|
alt="Avatar"
|
||||||
class="w-8 h-8 rounded-full"
|
class="w-8 h-8 rounded-full"
|
||||||
/>
|
/>
|
||||||
@@ -187,5 +186,5 @@ export default /* html */ `
|
|||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>\
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|||||||
@@ -8,19 +8,16 @@ export function createDemo<T extends Adapter<any, any>>(
|
|||||||
options?: Parameters<T>[0],
|
options?: Parameters<T>[0],
|
||||||
): ReturnType<T> {
|
): ReturnType<T> {
|
||||||
const hooks = defineHooks({
|
const hooks = defineHooks({
|
||||||
$(name, peer, ...args) {
|
|
||||||
console.log(
|
|
||||||
`$ ${peer} ${name} (${args.map((arg) => stringify(arg)).join(", ")})`,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
open(peer) {
|
open(peer) {
|
||||||
peer.send({ user: "system", message: `Welcome to the server ${peer}!` });
|
console.log(`[ws] open ${peer}`);
|
||||||
|
peer.send({ user: "server", message: `Welcome to the server ${peer}!` });
|
||||||
peer.subscribe("chat");
|
peer.subscribe("chat");
|
||||||
peer.publish("chat", { user: "system", message: `${peer} joined!` });
|
peer.publish("chat", { user: "server", message: `${peer} joined!` });
|
||||||
},
|
},
|
||||||
message(peer, message) {
|
message(peer, message) {
|
||||||
|
console.log(`[ws] message ${peer} ${message.text()}`);
|
||||||
if (message.text() === "ping") {
|
if (message.text() === "ping") {
|
||||||
peer.send({ user: "system", message: "pong" });
|
peer.send({ user: "server", message: "pong" });
|
||||||
} else {
|
} else {
|
||||||
const _message = {
|
const _message = {
|
||||||
user: peer.toString(),
|
user: peer.toString(),
|
||||||
@@ -31,6 +28,7 @@ export function createDemo<T extends Adapter<any, any>>(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
upgrade(req) {
|
upgrade(req) {
|
||||||
|
console.log("[ws] upgrade", req.url);
|
||||||
return {
|
return {
|
||||||
headers: {
|
headers: {
|
||||||
"x-powered-by": "cross-ws",
|
"x-powered-by": "cross-ws",
|
||||||
@@ -38,28 +36,18 @@ export function createDemo<T extends Adapter<any, any>>(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
close(peer, details) {
|
||||||
|
console.log(`[ws] close ${peer}`, details);
|
||||||
|
},
|
||||||
|
error(peer, error) {
|
||||||
|
console.log(`[ws] error ${peer}`, error);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const resolve: ResolveHooks = (info) => {
|
|
||||||
return {
|
|
||||||
open: (peer) => {
|
|
||||||
peer.send({
|
|
||||||
message: {
|
|
||||||
info: {
|
|
||||||
url: info.url,
|
|
||||||
headers:
|
|
||||||
info.headers && Object.fromEntries(new Headers(info.headers)),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return adapter({
|
return adapter({
|
||||||
...options,
|
...options,
|
||||||
hooks,
|
hooks,
|
||||||
resolve,
|
// resolve,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export default defineWebSocketAdapter<BunAdapter, BunOptions>(
|
|||||||
class BunPeer extends Peer<{
|
class BunPeer extends Peer<{
|
||||||
bun: { ws: ServerWebSocket<ContextData> };
|
bun: { ws: ServerWebSocket<ContextData> };
|
||||||
}> {
|
}> {
|
||||||
get id() {
|
get addr() {
|
||||||
let addr = this.ctx.bun.ws.remoteAddress;
|
let addr = this.ctx.bun.ws.remoteAddress;
|
||||||
if (addr.includes(":")) {
|
if (addr.includes(":")) {
|
||||||
addr = `[${addr}]`;
|
addr = `[${addr}]`;
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class CloudflarePeer extends Peer<{
|
|||||||
context: _cf.ExecutionContext;
|
context: _cf.ExecutionContext;
|
||||||
};
|
};
|
||||||
}> {
|
}> {
|
||||||
get id() {
|
get addr() {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class DenoPeer extends Peer<{
|
|||||||
info: ServeHandlerInfo;
|
info: ServeHandlerInfo;
|
||||||
};
|
};
|
||||||
}> {
|
}> {
|
||||||
get id() {
|
get addr() {
|
||||||
// @ts-expect-error types missing
|
// @ts-expect-error types missing
|
||||||
return this.ctx.deno.ws.remoteAddress;
|
return this.ctx.deno.ws.remoteAddress;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class NodePeer extends Peer<{
|
|||||||
ws: WebSocketT;
|
ws: WebSocketT;
|
||||||
};
|
};
|
||||||
}> {
|
}> {
|
||||||
get id() {
|
get addr() {
|
||||||
const socket = this.ctx.node.req.socket;
|
const socket = this.ctx.node.req.socket;
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ class UWSPeer extends Peer<{
|
|||||||
_headers: HeadersInit | undefined;
|
_headers: HeadersInit | undefined;
|
||||||
_decoder = new TextDecoder();
|
_decoder = new TextDecoder();
|
||||||
|
|
||||||
get id() {
|
get addr() {
|
||||||
try {
|
try {
|
||||||
const addr = this._decoder.decode(
|
const addr = this._decoder.decode(
|
||||||
this.ctx.uws.ws?.getRemoteAddressAsText(),
|
this.ctx.uws.ws?.getRemoteAddressAsText(),
|
||||||
|
|||||||
26
src/peer.ts
26
src/peer.ts
@@ -11,12 +11,21 @@ const ReadyStateMap = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export abstract class Peer<AdapterContext = any> implements WSRequest {
|
export abstract class Peer<AdapterContext = any> implements WSRequest {
|
||||||
_subscriptions: Set<string> = new Set();
|
private _subscriptions: Set<string> = new Set();
|
||||||
|
|
||||||
constructor(public ctx: AdapterContext) {}
|
static _idCounter = 0;
|
||||||
|
private _id: string;
|
||||||
|
|
||||||
get id(): string | undefined {
|
constructor(public ctx: AdapterContext) {
|
||||||
return "??";
|
this._id = ++Peer._idCounter + "";
|
||||||
|
}
|
||||||
|
|
||||||
|
get id(): string {
|
||||||
|
return this._id.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
get addr(): string | undefined {
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
get url(): string {
|
get url(): string {
|
||||||
@@ -46,10 +55,15 @@ export abstract class Peer<AdapterContext = any> implements WSRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
return `${this.id || ""}${this.readyState === 1 || this.readyState === -1 ? "" : ` [${ReadyStateMap[this.readyState]}]`}`;
|
return `#${this.id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Symbol.for("nodejs.util.inspect.custom")]() {
|
[Symbol.for("nodejs.util.inspect.custom")]() {
|
||||||
return this.toString();
|
const _addr = this.addr || "??";
|
||||||
|
const _state =
|
||||||
|
this.readyState === 1 || this.readyState === -1
|
||||||
|
? ""
|
||||||
|
: ` [${ReadyStateMap[this.readyState]}]`;
|
||||||
|
return `Peer<${_addr}${_state}>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user