bare-ws 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +4 -0
- package/lib/constants.d.ts +17 -0
- package/lib/constants.js +2 -3
- package/lib/errors.d.ts +28 -0
- package/lib/errors.js +12 -2
- package/lib/frame.js +2 -2
- package/lib/server.d.ts +63 -0
- package/lib/server.js +3 -3
- package/lib/socket.d.ts +41 -0
- package/lib/socket.js +15 -6
- package/package.json +28 -4
package/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Buffer from 'bare-buffer'
|
|
2
|
+
|
|
3
|
+
export const EOL: string
|
|
4
|
+
export const EOF: string
|
|
5
|
+
|
|
6
|
+
export const GUID: Buffer
|
|
7
|
+
|
|
8
|
+
export const opcode: {
|
|
9
|
+
CONTINUATION: number
|
|
10
|
+
TEXT: number
|
|
11
|
+
BINARY: number
|
|
12
|
+
CLOSE: number
|
|
13
|
+
PING: number
|
|
14
|
+
PONG: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const status: { PROTOCOL_ERROR: number; MESSAGE_TOO_LARGE: number }
|
package/lib/constants.js
CHANGED
package/lib/errors.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
declare class WebSocketError extends Error {
|
|
2
|
+
constructor(
|
|
3
|
+
msg: string,
|
|
4
|
+
code: string,
|
|
5
|
+
status: number,
|
|
6
|
+
fn?: WebSocketError,
|
|
7
|
+
cause?: unknown
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
static NETWORK_ERROR(msg: string, cause?: unknown): WebSocketError
|
|
11
|
+
static NOT_CONNECTED(msg?: string, cause?: unknown): WebSocketError
|
|
12
|
+
static UNEXPECTED_RSV1(msg?: string, cause?: unknown): WebSocketError
|
|
13
|
+
static UNEXPECTED_RSV2(msg?: string, cause?: unknown): WebSocketError
|
|
14
|
+
static UNEXPECTED_RSV3(msg?: string, cause?: unknown): WebSocketError
|
|
15
|
+
static EXPECTED_MASK(msg?: string, cause?: unknown): WebSocketError
|
|
16
|
+
static EXPECTED_CONTINUATION(msg?: string, cause?: unknown): WebSocketError
|
|
17
|
+
static UNEXPECTED_CONTINUATION(msg?: string, cause?: unknown): WebSocketError
|
|
18
|
+
static UNEXPECTED_CONTROL(msg?: string, cause?: unknown): WebSocketError
|
|
19
|
+
static INVALID_ENCODING(msg?: string, cause?: unknown): WebSocketError
|
|
20
|
+
static INVALID_UPGRADE_HEADER(msg?: string, cause?: unknown): WebSocketError
|
|
21
|
+
static INVALID_VERSION_HEADER(msg?: string, cause?: unknown): WebSocketError
|
|
22
|
+
static INVALID_KEY_HEADER(msg?: string, cause?: unknown): WebSocketError
|
|
23
|
+
static INVALID_ACCEPT_HEADER(msg?: string, cause?: unknown): WebSocketError
|
|
24
|
+
static INVALID_OPCODE(msg?: string, cause?: unknown): WebSocketError
|
|
25
|
+
static INVALID_PAYLOAD_LENGTH(msg?: string, cause?: unknown): WebSocketError
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export = WebSocketError
|
package/lib/errors.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const { status } = require('./constants')
|
|
2
2
|
|
|
3
3
|
module.exports = class WebSocketError extends Error {
|
|
4
|
-
constructor(msg, code, status, fn = WebSocketError) {
|
|
5
|
-
super(`${code}: ${msg}
|
|
4
|
+
constructor(msg, code, status, fn = WebSocketError, cause) {
|
|
5
|
+
super(`${code}: ${msg}`, { cause })
|
|
6
6
|
this.code = code
|
|
7
7
|
this.status = status
|
|
8
8
|
|
|
@@ -15,6 +15,16 @@ module.exports = class WebSocketError extends Error {
|
|
|
15
15
|
return 'WebSocketError'
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
static NETWORK_ERROR(msg, cause) {
|
|
19
|
+
return new WebSocketError(
|
|
20
|
+
msg,
|
|
21
|
+
'NETWORK_ERROR',
|
|
22
|
+
0,
|
|
23
|
+
WebSocketError.NETWORK_ERROR,
|
|
24
|
+
cause
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
18
28
|
static NOT_CONNECTED(msg = 'Socket is not connected') {
|
|
19
29
|
return new WebSocketError(
|
|
20
30
|
msg,
|
package/lib/frame.js
CHANGED
|
@@ -104,13 +104,13 @@ exports.encode = function encode(state, f) {
|
|
|
104
104
|
|
|
105
105
|
const high = Math.floor(length / 0x100000000)
|
|
106
106
|
|
|
107
|
-
v.
|
|
107
|
+
v.setUint32(i, high, false)
|
|
108
108
|
|
|
109
109
|
i += 4
|
|
110
110
|
|
|
111
111
|
const low = length & 0xffffffff
|
|
112
112
|
|
|
113
|
-
v.
|
|
113
|
+
v.setUint32(i, low, false)
|
|
114
114
|
|
|
115
115
|
i += 4
|
|
116
116
|
}
|
package/lib/server.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type HTTPSServerConnectionOptions } from 'bare-https'
|
|
2
|
+
import { HTTPClientRequest, type HTTPServerConnectionOptions } from 'bare-http1'
|
|
3
|
+
import { Socket as TCPSocket, type TCPSocketAddress } from 'bare-tcp'
|
|
4
|
+
import { type DuplexEvents } from 'bare-stream'
|
|
5
|
+
import EventEmitter from 'bare-events'
|
|
6
|
+
import Buffer from 'bare-buffer'
|
|
7
|
+
import WebSocket from './socket'
|
|
8
|
+
import WebSocketError from './errors'
|
|
9
|
+
|
|
10
|
+
interface WebSocketServerOptions
|
|
11
|
+
extends HTTPServerConnectionOptions,
|
|
12
|
+
HTTPSServerConnectionOptions {
|
|
13
|
+
secure?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface WebSocketServerEvents extends DuplexEvents {
|
|
17
|
+
connection: [socket: WebSocket, req: HTTPClientRequest]
|
|
18
|
+
listening: []
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface WebSocketServer<
|
|
22
|
+
M extends WebSocketServerEvents = WebSocketServerEvents
|
|
23
|
+
> extends EventEmitter<M> {
|
|
24
|
+
readonly listening: boolean
|
|
25
|
+
|
|
26
|
+
address(): TCPSocketAddress
|
|
27
|
+
close(cb?: (err: WebSocketError | null) => void): void
|
|
28
|
+
ref(): void
|
|
29
|
+
unref(): void
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare class WebSocketServer {
|
|
33
|
+
constructor(onconnection: (socket: WebSocket, req: HTTPClientRequest) => void)
|
|
34
|
+
|
|
35
|
+
constructor(
|
|
36
|
+
opts?: WebSocketServerOptions,
|
|
37
|
+
onconnection?: (socket: WebSocket, req: HTTPClientRequest) => void
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare namespace WebSocketServer {
|
|
42
|
+
export { type WebSocketServerOptions, type WebSocketServerEvents }
|
|
43
|
+
|
|
44
|
+
export function handshake(
|
|
45
|
+
req: HTTPClientRequest,
|
|
46
|
+
cb: (err: WebSocketError | null) => void
|
|
47
|
+
): void
|
|
48
|
+
|
|
49
|
+
export function handshake(
|
|
50
|
+
req: HTTPClientRequest,
|
|
51
|
+
socket: TCPSocket,
|
|
52
|
+
cb?: (err: WebSocketError | null) => void
|
|
53
|
+
): void
|
|
54
|
+
|
|
55
|
+
export function handshake(
|
|
56
|
+
req: HTTPClientRequest,
|
|
57
|
+
socket?: TCPSocket,
|
|
58
|
+
head?: Buffer,
|
|
59
|
+
cb?: (err: WebSocketError | null) => void
|
|
60
|
+
): void
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export = WebSocketServer
|
package/lib/server.js
CHANGED
|
@@ -71,7 +71,7 @@ module.exports = exports = class WebSocketServer extends EventEmitter {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
_onupgrade(req, socket, head) {
|
|
74
|
-
handshake(req, socket, head, (err) => {
|
|
74
|
+
exports.handshake(req, socket, head, (err) => {
|
|
75
75
|
if (err) return socket.destroy(err)
|
|
76
76
|
|
|
77
77
|
this.emit('connection', new WebSocket({ socket, isServer: true }), req)
|
|
@@ -80,7 +80,7 @@ module.exports = exports = class WebSocketServer extends EventEmitter {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// https://datatracker.ietf.org/doc/html/rfc6455#section-4.2
|
|
83
|
-
|
|
83
|
+
exports.handshake = function handshake(
|
|
84
84
|
req,
|
|
85
85
|
socket = req.socket,
|
|
86
86
|
head = EMPTY,
|
|
@@ -131,4 +131,4 @@ const handshake = (exports.handshake = function handshake(
|
|
|
131
131
|
if (head.byteLength) socket.unshift(head)
|
|
132
132
|
|
|
133
133
|
cb(null)
|
|
134
|
-
}
|
|
134
|
+
}
|
package/lib/socket.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { HTTPClientRequest } from 'bare-http1'
|
|
2
|
+
import { Socket as TCPSocket } from 'bare-tcp'
|
|
3
|
+
import { Duplex, type DuplexEvents } from 'bare-stream'
|
|
4
|
+
import URL from 'bare-url'
|
|
5
|
+
import WebSocketError from './errors'
|
|
6
|
+
|
|
7
|
+
interface WebSocketOptions {
|
|
8
|
+
host?: string
|
|
9
|
+
hostname?: string
|
|
10
|
+
path?: string
|
|
11
|
+
port?: string | number
|
|
12
|
+
secure?: boolean
|
|
13
|
+
socket?: TCPSocket
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface WebSocketEvents extends DuplexEvents {
|
|
17
|
+
ping: [payload: unknown]
|
|
18
|
+
pong: [payload: unknown]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface WebSocket<M extends WebSocketEvents = WebSocketEvents>
|
|
22
|
+
extends Duplex<M> {
|
|
23
|
+
ping(data: unknown): void
|
|
24
|
+
pong(data: unknown): void
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
declare class WebSocket {
|
|
28
|
+
constructor(opts: WebSocketOptions)
|
|
29
|
+
constructor(url: URL | string, opts?: WebSocketOptions)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
declare namespace WebSocket {
|
|
33
|
+
export { type WebSocketOptions, type WebSocketEvents }
|
|
34
|
+
|
|
35
|
+
export function handshake(
|
|
36
|
+
req: HTTPClientRequest,
|
|
37
|
+
cb: (error: WebSocketError | null) => void
|
|
38
|
+
): void
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export = WebSocket
|
package/lib/socket.js
CHANGED
|
@@ -81,7 +81,7 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
81
81
|
|
|
82
82
|
const req = request(opts)
|
|
83
83
|
|
|
84
|
-
handshake(req, (err) => {
|
|
84
|
+
exports.handshake(req, (err) => {
|
|
85
85
|
const cb = this._pendingOpen
|
|
86
86
|
this._pendingOpen = null
|
|
87
87
|
|
|
@@ -141,16 +141,20 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
141
141
|
if (frame.fin === false) {
|
|
142
142
|
if (this._fragments.push(frame) === 1) {
|
|
143
143
|
// First frame
|
|
144
|
-
if (frame.opcode === opcode.CONTINUATION)
|
|
144
|
+
if (frame.opcode === opcode.CONTINUATION) {
|
|
145
145
|
throw errors.UNEXPECTED_CONTINUATION()
|
|
146
|
+
}
|
|
146
147
|
|
|
147
|
-
if (frame.opcode >= opcode.CLOSE)
|
|
148
|
+
if (frame.opcode >= opcode.CLOSE) {
|
|
149
|
+
throw errors.UNEXPECTED_CONTROL()
|
|
150
|
+
}
|
|
148
151
|
|
|
149
152
|
return
|
|
150
153
|
}
|
|
151
154
|
|
|
152
|
-
if (frame.opcode !== opcode.CONTINUATION)
|
|
155
|
+
if (frame.opcode !== opcode.CONTINUATION) {
|
|
153
156
|
throw errors.EXPECTED_CONTINUATION()
|
|
157
|
+
}
|
|
154
158
|
|
|
155
159
|
return
|
|
156
160
|
}
|
|
@@ -234,12 +238,13 @@ module.exports = exports = class WebSocket extends Duplex {
|
|
|
234
238
|
}
|
|
235
239
|
|
|
236
240
|
_predestroy() {
|
|
241
|
+
if (!this._socket) return
|
|
237
242
|
this._socket.destroy()
|
|
238
243
|
}
|
|
239
244
|
}
|
|
240
245
|
|
|
241
246
|
// https://datatracker.ietf.org/doc/html/rfc6455#section-4.1
|
|
242
|
-
|
|
247
|
+
exports.handshake = function handshake(req, cb) {
|
|
243
248
|
const key = crypto.randomBytes(16).toString('base64')
|
|
244
249
|
|
|
245
250
|
req.headers = {
|
|
@@ -270,8 +275,12 @@ const handshake = (exports.handshake = function handshake(req, cb) {
|
|
|
270
275
|
cb(null)
|
|
271
276
|
})
|
|
272
277
|
|
|
278
|
+
req.on('error', (err) => {
|
|
279
|
+
cb(errors.NETWORK_ERROR('Network error', err))
|
|
280
|
+
})
|
|
281
|
+
|
|
273
282
|
req.end()
|
|
274
|
-
}
|
|
283
|
+
}
|
|
275
284
|
|
|
276
285
|
// https://url.spec.whatwg.org/#default-port
|
|
277
286
|
function defaultPort(url) {
|
package/package.json
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bare-ws",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "WebSocket library for JavaScript",
|
|
5
5
|
"exports": {
|
|
6
|
-
".":
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./index.d.ts",
|
|
8
|
+
"default": "./index.js"
|
|
9
|
+
},
|
|
7
10
|
"./package": "./package.json",
|
|
8
|
-
"./constants":
|
|
9
|
-
|
|
11
|
+
"./constants": {
|
|
12
|
+
"types": "./lib/constants.d.ts",
|
|
13
|
+
"default": "./lib/constants.js"
|
|
14
|
+
},
|
|
15
|
+
"./errors": {
|
|
16
|
+
"types": "./lib/errors.d.ts",
|
|
17
|
+
"default": "./lib/errors.js"
|
|
18
|
+
}
|
|
10
19
|
},
|
|
11
20
|
"files": [
|
|
12
21
|
"index.js",
|
|
22
|
+
"index.d.ts",
|
|
13
23
|
"lib"
|
|
14
24
|
],
|
|
15
25
|
"scripts": {
|
|
@@ -33,9 +43,23 @@
|
|
|
33
43
|
"bare-stream": "^2.1.2"
|
|
34
44
|
},
|
|
35
45
|
"devDependencies": {
|
|
46
|
+
"bare-buffer": "^3.0.2",
|
|
36
47
|
"bare-fs": "^4.0.0",
|
|
48
|
+
"bare-url": "^2.1.3",
|
|
37
49
|
"brittle": "^3.3.0",
|
|
38
50
|
"prettier": "^3.4.1",
|
|
39
51
|
"prettier-config-standard": "^7.0.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"bare-buffer": "*",
|
|
55
|
+
"bare-url": "*"
|
|
56
|
+
},
|
|
57
|
+
"peerDependenciesMeta": {
|
|
58
|
+
"bare-buffer": {
|
|
59
|
+
"optional": true
|
|
60
|
+
},
|
|
61
|
+
"bare-url": {
|
|
62
|
+
"optional": true
|
|
63
|
+
}
|
|
40
64
|
}
|
|
41
65
|
}
|