|
| 1 | +# Socket.IO server for Deno |
| 2 | + |
| 3 | +An implementation of the Socket.IO protocol for Deno. |
| 4 | + |
| 5 | +Table of content: |
| 6 | + |
| 7 | +- [Usage](#usage) |
| 8 | +- [Options](#options) |
| 9 | + - [`path`](#path) |
| 10 | + - [`connectTimeout`](#connecttimeout) |
| 11 | + - [`pingTimeout`](#pingtimeout) |
| 12 | + - [`pingInterval`](#pinginterval) |
| 13 | + - [`upgradeTimeout`](#upgradetimeout) |
| 14 | + - [`maxHttpBufferSize`](#maxhttpbuffersize) |
| 15 | + - [`allowRequest`](#allowrequest) |
| 16 | + - [`cors`](#cors) |
| 17 | + - [`editHandshakeHeaders`](#edithandshakeheaders) |
| 18 | + - [`editResponseHeaders`](#editresponseheaders) |
| 19 | +- [Logs](#logs) |
| 20 | + |
| 21 | +## Usage |
| 22 | + |
| 23 | +```ts |
| 24 | +import { serve } from "https://deno.land/[email protected]/http/server.ts"; |
| 25 | +import { Server } from "https://deno.land/x/[email protected]/mod.ts"; |
| 26 | + |
| 27 | +const io = new Server(); |
| 28 | + |
| 29 | +io.on("connection", (socket) => { |
| 30 | + console.log(`socket ${socket.id} connected`); |
| 31 | + |
| 32 | + socket.emit("hello", "world"); |
| 33 | + |
| 34 | + socket.on("disconnect", (reason) => { |
| 35 | + console.log(`socket ${socket.id} disconnected due to ${reason}`); |
| 36 | + }); |
| 37 | +}); |
| 38 | + |
| 39 | +await serve(io.handler(), { |
| 40 | + port: 3000, |
| 41 | +}); |
| 42 | +``` |
| 43 | + |
| 44 | +And then run with: |
| 45 | + |
| 46 | +``` |
| 47 | +$ deno run --allow-net index.ts |
| 48 | +``` |
| 49 | + |
| 50 | +Like the [Node.js server](https://socket.io/docs/v4/typescript/), you can also |
| 51 | +provide types for the events sent between the server and the clients: |
| 52 | + |
| 53 | +```ts |
| 54 | +interface ServerToClientEvents { |
| 55 | + noArg: () => void; |
| 56 | + basicEmit: (a: number, b: string, c: Buffer) => void; |
| 57 | + withAck: (d: string, callback: (e: number) => void) => void; |
| 58 | +} |
| 59 | + |
| 60 | +interface ClientToServerEvents { |
| 61 | + hello: () => void; |
| 62 | +} |
| 63 | + |
| 64 | +interface InterServerEvents { |
| 65 | + ping: () => void; |
| 66 | +} |
| 67 | + |
| 68 | +interface SocketData { |
| 69 | + user_id: string; |
| 70 | +} |
| 71 | + |
| 72 | +const io = new Server< |
| 73 | + ClientToServerEvents, |
| 74 | + ServerToClientEvents, |
| 75 | + InterServerEvents, |
| 76 | + SocketData |
| 77 | +>(); |
| 78 | +``` |
| 79 | + |
| 80 | +## Options |
| 81 | + |
| 82 | +### `path` |
| 83 | + |
| 84 | +Default value: `/socket.io/` |
| 85 | + |
| 86 | +It is the name of the path that is captured on the server side. |
| 87 | + |
| 88 | +Caution! The server and the client values must match (unless you are using a |
| 89 | +path-rewriting proxy in between). |
| 90 | + |
| 91 | +Example: |
| 92 | + |
| 93 | +```ts |
| 94 | +const io = new Server(httpServer, { |
| 95 | + path: "/my-custom-path/", |
| 96 | +}); |
| 97 | +``` |
| 98 | + |
| 99 | +### `connectTimeout` |
| 100 | + |
| 101 | +Default value: `45000` |
| 102 | + |
| 103 | +The number of ms before disconnecting a client that has not successfully joined |
| 104 | +a namespace. |
| 105 | + |
| 106 | +### `pingTimeout` |
| 107 | + |
| 108 | +Default value: `20000` |
| 109 | + |
| 110 | +This value is used in the heartbeat mechanism, which periodically checks if the |
| 111 | +connection is still alive between the server and the client. |
| 112 | + |
| 113 | +The server sends a ping, and if the client does not answer with a pong within |
| 114 | +`pingTimeout` ms, the server considers that the connection is closed. |
| 115 | + |
| 116 | +Similarly, if the client does not receive a ping from the server within |
| 117 | +`pingInterval + pingTimeout` ms, the client also considers that the connection |
| 118 | +is closed. |
| 119 | + |
| 120 | +### `pingInterval` |
| 121 | + |
| 122 | +Default value: `25000` |
| 123 | + |
| 124 | +See [`pingTimeout`](#pingtimeout) for more explanation. |
| 125 | + |
| 126 | +### `upgradeTimeout` |
| 127 | + |
| 128 | +Default value: `10000` |
| 129 | + |
| 130 | +This is the delay in milliseconds before an uncompleted transport upgrade is |
| 131 | +cancelled. |
| 132 | + |
| 133 | +### `maxHttpBufferSize` |
| 134 | + |
| 135 | +Default value: `1e6` (1 MB) |
| 136 | + |
| 137 | +This defines how many bytes a single message can be, before closing the socket. |
| 138 | +You may increase or decrease this value depending on your needs. |
| 139 | + |
| 140 | +### `allowRequest` |
| 141 | + |
| 142 | +Default value: `-` |
| 143 | + |
| 144 | +A function that receives a given handshake or upgrade request as its first |
| 145 | +parameter, and can decide whether to continue or not. |
| 146 | + |
| 147 | +Example: |
| 148 | + |
| 149 | +```ts |
| 150 | +const io = new Server({ |
| 151 | + allowRequest: (req, connInfo) => { |
| 152 | + return Promise.reject("thou shall not pass"); |
| 153 | + }, |
| 154 | +}); |
| 155 | +``` |
| 156 | + |
| 157 | +### `cors` |
| 158 | + |
| 159 | +Default value: `-` |
| 160 | + |
| 161 | +A set of options related to |
| 162 | +[Cross-Origin Resource Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) |
| 163 | +(CORS). |
| 164 | + |
| 165 | +Example: |
| 166 | + |
| 167 | +```ts |
| 168 | +const io = new Server({ |
| 169 | + cors: { |
| 170 | + origin: ["https://example.com"], |
| 171 | + allowedHeaders: ["my-header"], |
| 172 | + credentials: true, |
| 173 | + }, |
| 174 | +}); |
| 175 | +``` |
| 176 | + |
| 177 | +### `editHandshakeHeaders` |
| 178 | + |
| 179 | +Default value: `-` |
| 180 | + |
| 181 | +A function that allows to edit the response headers of the handshake request. |
| 182 | + |
| 183 | +Example: |
| 184 | + |
| 185 | +```ts |
| 186 | +const io = new Server({ |
| 187 | + editHandshakeHeaders: (responseHeaders, req, connInfo) => { |
| 188 | + responseHeaders.set("set-cookie", "sid=1234"); |
| 189 | + }, |
| 190 | +}); |
| 191 | +``` |
| 192 | + |
| 193 | +### `editResponseHeaders` |
| 194 | + |
| 195 | +Default value: `-` |
| 196 | + |
| 197 | +A function that allows to edit the response headers of all requests. |
| 198 | + |
| 199 | +Example: |
| 200 | + |
| 201 | +```ts |
| 202 | +const io = new Server({ |
| 203 | + editResponseHeaders: (responseHeaders, req, connInfo) => { |
| 204 | + responseHeaders.set("my-header", "abcd"); |
| 205 | + }, |
| 206 | +}); |
| 207 | +``` |
| 208 | + |
| 209 | +## Logs |
| 210 | + |
| 211 | +The library relies on the standard `log` module, so you can display the internal |
| 212 | +logs of the Socket.IO server with: |
| 213 | + |
| 214 | +```ts |
| 215 | +import * as log from "https://deno.land/[email protected]/log/mod.ts"; |
| 216 | + |
| 217 | +await log.setup({ |
| 218 | + handlers: { |
| 219 | + console: new log.handlers.ConsoleHandler("DEBUG"), |
| 220 | + }, |
| 221 | + loggers: { |
| 222 | + "socket.io": { |
| 223 | + level: "DEBUG", |
| 224 | + handlers: ["console"], |
| 225 | + }, |
| 226 | + "engine.io": { |
| 227 | + level: "DEBUG", |
| 228 | + handlers: ["console"], |
| 229 | + }, |
| 230 | + }, |
| 231 | +}); |
| 232 | +``` |
| 233 | + |
| 234 | +## License |
| 235 | + |
| 236 | +[ISC](/LICENSE) |
0 commit comments