-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit e892ecf
Showing
44 changed files
with
7,384 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
name: CI | ||
|
||
on: | ||
push: | ||
pull_request: | ||
schedule: | ||
- cron: "0 0 * * 0" | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
deno-version: | ||
- 1.25.2 | ||
|
||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v2 | ||
|
||
- name: Use Deno ${{ matrix.deno-version }} | ||
uses: denolib/setup-deno@v2 | ||
with: | ||
deno-version: ${{ matrix.deno-version }} | ||
|
||
- name: Check format | ||
run: deno fmt --check | ||
|
||
- name: Run tests | ||
run: deno test --allow-net |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
ISC License | ||
|
||
Copyright (c) 2022 Damien ARRACHEQUESNE | ||
|
||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted, provided that the above | ||
copyright notice and this permission notice appear in all copies. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
# Socket.IO server for Deno | ||
|
||
An implementation of the Socket.IO protocol for Deno. | ||
|
||
Table of content: | ||
|
||
- [Usage](#usage) | ||
- [Options](#options) | ||
- [`path`](#path) | ||
- [`connectTimeout`](#connecttimeout) | ||
- [`pingTimeout`](#pingtimeout) | ||
- [`pingInterval`](#pinginterval) | ||
- [`upgradeTimeout`](#upgradetimeout) | ||
- [`maxHttpBufferSize`](#maxhttpbuffersize) | ||
- [`allowRequest`](#allowrequest) | ||
- [`cors`](#cors) | ||
- [`editHandshakeHeaders`](#edithandshakeheaders) | ||
- [`editResponseHeaders`](#editresponseheaders) | ||
- [Logs](#logs) | ||
|
||
## Usage | ||
|
||
```ts | ||
import { serve } from "https://deno.land/[email protected]/http/server.ts"; | ||
import { Server } from "https://deno.land/x/[email protected]/mod.ts"; | ||
|
||
const io = new Server(); | ||
|
||
io.on("connection", (socket) => { | ||
console.log(`socket ${socket.id} connected`); | ||
|
||
socket.emit("hello", "world"); | ||
|
||
socket.on("disconnect", (reason) => { | ||
console.log(`socket ${socket.id} disconnected due to ${reason}`); | ||
}); | ||
}); | ||
|
||
await serve(io.handler(), { | ||
port: 3000, | ||
}); | ||
``` | ||
|
||
And then run with: | ||
|
||
``` | ||
$ deno run --allow-net index.ts | ||
``` | ||
|
||
Like the [Node.js server](https://socket.io/docs/v4/typescript/), you can also | ||
provide types for the events sent between the server and the clients: | ||
|
||
```ts | ||
interface ServerToClientEvents { | ||
noArg: () => void; | ||
basicEmit: (a: number, b: string, c: Buffer) => void; | ||
withAck: (d: string, callback: (e: number) => void) => void; | ||
} | ||
|
||
interface ClientToServerEvents { | ||
hello: () => void; | ||
} | ||
|
||
interface InterServerEvents { | ||
ping: () => void; | ||
} | ||
|
||
interface SocketData { | ||
user_id: string; | ||
} | ||
|
||
const io = new Server< | ||
ClientToServerEvents, | ||
ServerToClientEvents, | ||
InterServerEvents, | ||
SocketData | ||
>(); | ||
``` | ||
|
||
## Options | ||
|
||
### `path` | ||
|
||
Default value: `/socket.io/` | ||
|
||
It is the name of the path that is captured on the server side. | ||
|
||
Caution! The server and the client values must match (unless you are using a | ||
path-rewriting proxy in between). | ||
|
||
Example: | ||
|
||
```ts | ||
const io = new Server(httpServer, { | ||
path: "/my-custom-path/", | ||
}); | ||
``` | ||
|
||
### `connectTimeout` | ||
|
||
Default value: `45000` | ||
|
||
The number of ms before disconnecting a client that has not successfully joined | ||
a namespace. | ||
|
||
### `pingTimeout` | ||
|
||
Default value: `20000` | ||
|
||
This value is used in the heartbeat mechanism, which periodically checks if the | ||
connection is still alive between the server and the client. | ||
|
||
The server sends a ping, and if the client does not answer with a pong within | ||
`pingTimeout` ms, the server considers that the connection is closed. | ||
|
||
Similarly, if the client does not receive a ping from the server within | ||
`pingInterval + pingTimeout` ms, the client also considers that the connection | ||
is closed. | ||
|
||
### `pingInterval` | ||
|
||
Default value: `25000` | ||
|
||
See [`pingTimeout`](#pingtimeout) for more explanation. | ||
|
||
### `upgradeTimeout` | ||
|
||
Default value: `10000` | ||
|
||
This is the delay in milliseconds before an uncompleted transport upgrade is | ||
cancelled. | ||
|
||
### `maxHttpBufferSize` | ||
|
||
Default value: `1e6` (1 MB) | ||
|
||
This defines how many bytes a single message can be, before closing the socket. | ||
You may increase or decrease this value depending on your needs. | ||
|
||
### `allowRequest` | ||
|
||
Default value: `-` | ||
|
||
A function that receives a given handshake or upgrade request as its first | ||
parameter, and can decide whether to continue or not. | ||
|
||
Example: | ||
|
||
```ts | ||
const io = new Server({ | ||
allowRequest: (req, connInfo) => { | ||
return Promise.reject("thou shall not pass"); | ||
}, | ||
}); | ||
``` | ||
|
||
### `cors` | ||
|
||
Default value: `-` | ||
|
||
A set of options related to | ||
[Cross-Origin Resource Sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) | ||
(CORS). | ||
|
||
Example: | ||
|
||
```ts | ||
const io = new Server({ | ||
cors: { | ||
origin: ["https://example.com"], | ||
allowedHeaders: ["my-header"], | ||
credentials: true, | ||
}, | ||
}); | ||
``` | ||
|
||
### `editHandshakeHeaders` | ||
|
||
Default value: `-` | ||
|
||
A function that allows to edit the response headers of the handshake request. | ||
|
||
Example: | ||
|
||
```ts | ||
const io = new Server({ | ||
editHandshakeHeaders: (responseHeaders, req, connInfo) => { | ||
responseHeaders.set("set-cookie", "sid=1234"); | ||
}, | ||
}); | ||
``` | ||
|
||
### `editResponseHeaders` | ||
|
||
Default value: `-` | ||
|
||
A function that allows to edit the response headers of all requests. | ||
|
||
Example: | ||
|
||
```ts | ||
const io = new Server({ | ||
editResponseHeaders: (responseHeaders, req, connInfo) => { | ||
responseHeaders.set("my-header", "abcd"); | ||
}, | ||
}); | ||
``` | ||
|
||
## Logs | ||
|
||
The library relies on the standard `log` module, so you can display the internal | ||
logs of the Socket.IO server with: | ||
|
||
```ts | ||
import * as log from "https://deno.land/[email protected]/log/mod.ts"; | ||
|
||
await log.setup({ | ||
handlers: { | ||
console: new log.handlers.ConsoleHandler("DEBUG"), | ||
}, | ||
loggers: { | ||
"socket.io": { | ||
level: "DEBUG", | ||
handlers: ["console"], | ||
}, | ||
"engine.io": { | ||
level: "DEBUG", | ||
handlers: ["console"], | ||
}, | ||
}, | ||
}); | ||
``` | ||
|
||
## License | ||
|
||
[ISC](/LICENSE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export { | ||
type ConnInfo, | ||
type Handler, | ||
} from "https://deno.land/[email protected]/http/server.ts"; | ||
|
||
export { getLogger } from "https://deno.land/[email protected]/log/mod.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { Server, type ServerOptions } from "./packages/socket.io/mod.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
const chars = | ||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
|
||
// Use a lookup table to find the index. | ||
const lookup = new Uint8Array(256); | ||
for (let i = 0; i < chars.length; i++) { | ||
lookup[chars.charCodeAt(i)] = i; | ||
} | ||
|
||
export function encodeToBase64(arraybuffer: ArrayBuffer): string { | ||
const bytes = new Uint8Array(arraybuffer); | ||
const len = bytes.length; | ||
let base64 = ""; | ||
|
||
for (let i = 0; i < len; i += 3) { | ||
base64 += chars[bytes[i] >> 2]; | ||
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; | ||
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; | ||
base64 += chars[bytes[i + 2] & 63]; | ||
} | ||
|
||
if (len % 3 === 2) { | ||
base64 = base64.substring(0, base64.length - 1) + "="; | ||
} else if (len % 3 === 1) { | ||
base64 = base64.substring(0, base64.length - 2) + "=="; | ||
} | ||
|
||
return base64; | ||
} | ||
|
||
export function decodeFromBase64(base64: string): ArrayBuffer { | ||
const len = base64.length; | ||
let bufferLength = base64.length * 0.75, | ||
i, | ||
p = 0, | ||
encoded1, | ||
encoded2, | ||
encoded3, | ||
encoded4; | ||
|
||
if (base64[base64.length - 1] === "=") { | ||
bufferLength--; | ||
if (base64[base64.length - 2] === "=") { | ||
bufferLength--; | ||
} | ||
} | ||
|
||
const arraybuffer = new ArrayBuffer(bufferLength), | ||
bytes = new Uint8Array(arraybuffer); | ||
|
||
for (i = 0; i < len; i += 4) { | ||
encoded1 = lookup[base64.charCodeAt(i)]; | ||
encoded2 = lookup[base64.charCodeAt(i + 1)]; | ||
encoded3 = lookup[base64.charCodeAt(i + 2)]; | ||
encoded4 = lookup[base64.charCodeAt(i + 3)]; | ||
|
||
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); | ||
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); | ||
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); | ||
} | ||
|
||
return arraybuffer; | ||
} |
Oops, something went wrong.