Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from websockets:master #2

Open
wants to merge 117 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
d68ba9e
[security] Drop sensitive headers when following insecure redirects
lpinca May 25, 2022
903ec62
[doc] Update the type of the `socket` argument
lpinca May 25, 2022
6e5a5ce
[feature] Introduce the `'wsClientError'` event (#2046)
lpinca May 26, 2022
4b62fbf
[dist] 8.7.0
lpinca May 26, 2022
5e4149e
[test] Fix typo
lpinca May 30, 2022
a6dbd1c
[ci] Set permissions explicitly (#2051)
neilnaveen Jun 4, 2022
c1a126f
[doc] Rename WS Error Codes section to Error codes
lpinca Jun 8, 2022
0792742
[doc] Fix nit
lpinca Jun 8, 2022
becf237
[feature] Add the `WS_NO_{BUFFER_UTIL, UTF_8_VALIDATE}` variables
lpinca Jun 9, 2022
982b782
[dist] 8.8.0
lpinca Jun 9, 2022
3b6af82
[minor] Prevent opening handshake headers from being overridden
lpinca Jun 20, 2022
1117af6
[doc] Fix typo (#2062)
leetrout Jun 30, 2022
0ae302a
[test] Fix nits
lpinca Jul 14, 2022
bc8bd34
[security] Fix same host check for ws+unix: redirects
lpinca Jul 15, 2022
9753821
[dist] 8.8.1
lpinca Jul 15, 2022
c22cbc9
[doc] Revise `WebSocket#send()` docs for clarity (#2077)
DLiblik Sep 18, 2022
2995349
[minor] Simplify the ws+unix: URL form
lpinca Sep 20, 2022
6b71a49
[minor] Rename the `invalidURLMessage` variable
lpinca Sep 21, 2022
0da6036
[test] Remove leftover from test
lpinca Sep 21, 2022
4ed2c87
[doc] Remove "note that"
lpinca Sep 21, 2022
7ff26d9
[doc] Fix nits
lpinca Sep 21, 2022
e628f2b
[feature] Support Windows named pipes (#2079)
lpinca Sep 22, 2022
966f9d4
[dist] 8.9.0
lpinca Sep 22, 2022
c4d6eb3
[ci] Do not use the set-output command
lpinca Oct 20, 2022
211d5d3
[pkg] Add package.json export
lpinca Oct 24, 2022
cdca711
[dist] 8.10.0
lpinca Oct 24, 2022
38f7879
[ci] Test on node 19
lpinca Nov 2, 2022
9ab743a
[feature] Add support for objets with a `handleEvent()` method
lpinca Nov 4, 2022
1cec17d
[fix] Add the same event listener only once
lpinca Nov 4, 2022
afd8c62
[dist] 8.11.0
lpinca Nov 6, 2022
ea76193
[doc] Improve doc for the `callback` argument of `WebSocketServer`
lpinca Nov 25, 2022
8a8fc88
[minor] Validate the payload length of the close frame sooner
lpinca Dec 9, 2022
a6fa37a
[license] Update copyright notice
lpinca Dec 9, 2022
9e0fd77
[minor] Use `Buffer#subarray()` instead of `Buffer#slice()`
lpinca Dec 12, 2022
e6a32f8
[perf] Use `FastBuffer` instead of `Buffer#subarray()`
lpinca Dec 13, 2022
1b057f9
[minor] Fix nit
lpinca Dec 13, 2022
83c72cf
[perf] Make `toBuffer()` use `FastBuffer`
lpinca Dec 13, 2022
fb1dfd2
[doc] Fix badge URL
lpinca Dec 16, 2022
2dc2812
[minor] Make `sendAfterClose()` call the callback in the next tick
lpinca Dec 20, 2022
d412358
[minor] Fix nits
lpinca Dec 20, 2022
ff63bba
[pkg] Update utf-8-validate to version 6.0.0
lpinca Jan 6, 2023
42d79f6
[minor] Use `buffer.isUtf8()` if possible
lpinca Jan 7, 2023
a3214d3
[dist] 8.12.0
lpinca Jan 7, 2023
2862c2f
[doc] Add error handlers to examples and code snippets
lpinca Jan 23, 2023
0d114ef
[pkg] Add browser condition (#2118)
flashd2n Feb 13, 2023
a04578e
[dist] 8.12.1
lpinca Feb 13, 2023
41dc56a
[doc] Remove misleading information
lpinca Feb 14, 2023
b4b9d5a
[test] Fix failing test when using the domain module (#2126)
mvduin Mar 9, 2023
cd89e07
[feature] Add option to support late addition of headers (#2123)
mvduin Mar 10, 2023
23acf8c
[test] Fix nits
lpinca Mar 10, 2023
45e17ac
[pkg] 8.13.0
lpinca Mar 10, 2023
5bdc880
[ci] Do not test on node 19
lpinca Apr 19, 2023
d1bb536
[ci] Test on node 20
lpinca Apr 19, 2023
06728e4
[ci] Update coverallsapp/github-action action to v2
lpinca Apr 25, 2023
0368beb
[pkg] Update prettier to version 3.0.0
lpinca Jul 11, 2023
12a0a9c
[pkg] Update eslint-plugin-prettier to version 5.0.0
lpinca Jul 11, 2023
0b235e0
[ci] Run the lint step on node 20
lpinca Jul 11, 2023
8f5cc9d
[pkg] Update eslint-config-prettier to version 9.0.0
lpinca Aug 19, 2023
5299b0e
[test] Remove redundant tests
lpinca Aug 20, 2023
8eb2c47
[test] Fix nits
lpinca Aug 20, 2023
67007fc
[test] Reduce message size from 20 MiB to 4 MiB
lpinca Aug 21, 2023
79dab96
[fix] Emit at most one event per microtask (#2160)
lpinca Aug 28, 2023
347aab6
[feature] Allow http and https schemes (#2162)
lpinca Aug 28, 2023
31da417
[fix] Make `server.handleUpgrade()` work with any duplex stream (#2165)
pimterry Aug 31, 2023
62521f2
[minor] Fix nits
lpinca Aug 31, 2023
5b577fe
[pkg] Remove native-duplexpair dev dependency
lpinca Sep 6, 2023
c1d26c3
[test] Fix failing test
lpinca Sep 6, 2023
d307684
[dist] 8.14.0
lpinca Sep 6, 2023
ddba690
[doc] Fix the type of the `socket` argument
lpinca Sep 6, 2023
511aefe
[pkg] Silence npm warning
lpinca Sep 6, 2023
ae60ce0
[ci] Cache downloaded npm dependencies (#2166)
jerome-benoit Sep 8, 2023
fd3c64c
[test] Fix flaky tests on Windows
lpinca Sep 8, 2023
397b89e
[ci] Update actions/checkout action to v4
lpinca Sep 8, 2023
7460049
[dist] 8.14.1
lpinca Sep 8, 2023
7f4e1a7
[fix] Add missing rejection handler
lpinca Sep 19, 2023
d8dd485
[dist] 8.14.2
lpinca Sep 19, 2023
a049674
[ci] Update actions/setup-node action to v4
lpinca Nov 4, 2023
726abc3
[test] Fix flaky test
lpinca Dec 8, 2023
208220d
[lint] Fix prettier error
lpinca Dec 8, 2023
dd1994d
[ci] Test on node 21
lpinca Dec 8, 2023
5a3036e
[test] Merge some tests
lpinca Dec 9, 2023
c320738
[test] Fix nits
lpinca Dec 9, 2023
603a039
[doc] Add JSDoc for the `finishRequest` option
lpinca Dec 9, 2023
93e3552
[feature] Introduce the `allowMultipleEventsPerMicrotask` option
lpinca Dec 9, 2023
297fff8
[dist] 8.15.0
lpinca Dec 9, 2023
fccc580
[fix] Emit the event when the microtask is executed
lpinca Dec 12, 2023
4ed7fe5
[major] Rename the `allowMultipleEventsPerMicrotask` option
lpinca Dec 12, 2023
a57e963
[dist] 8.15.1
lpinca Dec 12, 2023
d37756a
[doc] Clarify legacy deps (#2184)
Zamiell Dec 20, 2023
3e230c1
[doc] Fix nits
lpinca Dec 20, 2023
527ec97
[doc] Add missing subsubsection to TOC
lpinca Dec 20, 2023
01ba54e
[feature] Introduce the `autoPong` option
lpinca Dec 25, 2023
391ddf3
[test] Use `stream.getDefaultHighWaterMark()` when available
lpinca Dec 26, 2023
d343a0c
[dist] 8.16.0
lpinca Dec 26, 2023
5e42cfd
[meta] Add FUNDING.json
lpinca Jan 24, 2024
8be840e
[doc] Replace `url.parse()` with `new URL()` (#2208)
Al-phonsio Mar 16, 2024
2405c17
[doc] Add punctuation for readability (#2213)
grjan7 Mar 29, 2024
b119b41
[pkg] Update eslint to version 9.0.0
lpinca Apr 9, 2024
53a8888
[feature] Allow the `createConnection` option (#2219)
pimterry Apr 15, 2024
2aa0405
[minor] Fix nits
lpinca Apr 15, 2024
e5f32c7
[fix] Emit at most one event per event loop iteration (#2218)
lpinca Apr 24, 2024
96c9b3d
[major] Flip the default value of `allowSynchronousEvents` (#2221)
lpinca Apr 24, 2024
1817bac
[ci] Do not test on node 21
lpinca Apr 26, 2024
934c9d6
[ci] Test on node 22
lpinca Apr 26, 2024
29694a5
[test] Use the `highWaterMark` variable
lpinca Apr 26, 2024
b73b118
[dist] 8.17.0
lpinca Apr 28, 2024
ddfe4a8
[perf] Reduce the amount of `crypto.randomFillSync()` calls
lpinca May 18, 2024
6a00029
[test] Increase code coverage
lpinca Jun 13, 2024
e55e510
[security] Fix crash when the Upgrade header cannot be read (#2231)
lpinca Jun 16, 2024
3c56601
[dist] 8.17.1
lpinca Jun 16, 2024
15f11a0
[security] Add new DoS vulnerability to SECURITY.md
lpinca Jun 16, 2024
0d1b5e6
[security] Use more descriptive text for 2017 vulnerability link
lpinca Jun 16, 2024
59b9629
[feature] Add support for `Blob` (#2229)
lpinca Jul 2, 2024
976c53c
[dist] 8.18.0
lpinca Jul 3, 2024
f7dc469
[doc] Fix the type of the `data` argument
lpinca Jul 4, 2024
bfe1b2a
[doc] Remove unnecessary period (#2240)
yuhao423 Jul 4, 2024
019f28f
[minor] Improve JSDoc-inferred types (#2242)
ITenthusiasm Jul 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[feature] Support Windows named pipes (websockets#2079)
Document how to connect to a named pipe endpoint and the limitations.

Refs: websockets#1808
Refs: websockets#2075
  • Loading branch information
lpinca committed Sep 22, 2022
commit e628f2bdb6277fa36e8607cf1c3fbaf713f7bcef
28 changes: 19 additions & 9 deletions doc/ws.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
- [Class: WebSocket](#class-websocket)
- [Ready state constants](#ready-state-constants)
- [new WebSocket(address[, protocols][, options])](#new-websocketaddress-protocols-options)
- [UNIX Domain Sockets](#unix-domain-sockets)
- [IPC connections](#ipc-connections)
- [Event: 'close'](#event-close-1)
- [Event: 'error'](#event-error-1)
- [Event: 'message'](#event-message)
Expand Down Expand Up @@ -323,17 +323,27 @@ context takeover.

Create a new WebSocket instance.

#### UNIX Domain Sockets
#### IPC connections

`ws` supports making requests to UNIX domain sockets. To make one, use the
following URL form:
`ws` supports IPC connections. To connect to an IPC endpoint, use the following
URL form:

```
ws+unix:/absolute/path/to/uds_socket:/pathname?search_params
```
- On Unices

```
ws+unix:/absolute/path/to/uds_socket:/pathname?search_params
```

- On Windows

```
ws+unix:\\.\pipe\pipe_name:/pathname?search_params
```

The character `:` is the separator between the socket path and the URL path. If
the URL path is omitted
The character `:` is the separator between the IPC path (the Unix domain socket
path or the Windows named pipe) and the URL path. The IPC path must not include
the characters `:` and `?`, otherwise the URL is incorrectly parsed. If the URL
path is omitted

```
ws+unix:/absolute/path/to/uds_socket
Expand Down
18 changes: 9 additions & 9 deletions lib/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -677,13 +677,13 @@ function initAsClient(websocket, address, protocols, options) {
}

const isSecure = parsedUrl.protocol === 'wss:';
const isUnixSocket = parsedUrl.protocol === 'ws+unix:';
const isIpcUrl = parsedUrl.protocol === 'ws+unix:';
let invalidUrlMessage;

if (parsedUrl.protocol !== 'ws:' && !isSecure && !isUnixSocket) {
if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {
invalidUrlMessage =
'The URL\'s protocol must be one of "ws:", "wss:", or "ws+unix:"';
} else if (isUnixSocket && !parsedUrl.pathname) {
} else if (isIpcUrl && !parsedUrl.pathname) {
invalidUrlMessage = "The URL's pathname is empty";
} else if (parsedUrl.hash) {
invalidUrlMessage = 'The URL contains a fragment identifier';
Expand Down Expand Up @@ -760,7 +760,7 @@ function initAsClient(websocket, address, protocols, options) {
opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
}

if (isUnixSocket) {
if (isIpcUrl) {
const parts = opts.path.split(':');

opts.socketPath = parts[0];
Expand All @@ -771,9 +771,9 @@ function initAsClient(websocket, address, protocols, options) {

if (opts.followRedirects) {
if (websocket._redirects === 0) {
websocket._originalUnixSocket = isUnixSocket;
websocket._originalIpc = isIpcUrl;
websocket._originalSecure = isSecure;
websocket._originalHostOrSocketPath = isUnixSocket
websocket._originalHostOrSocketPath = isIpcUrl
? opts.socketPath
: parsedUrl.host;

Expand All @@ -791,11 +791,11 @@ function initAsClient(websocket, address, protocols, options) {
}
}
} else if (websocket.listenerCount('redirect') === 0) {
const isSameHost = isUnixSocket
? websocket._originalUnixSocket
const isSameHost = isIpcUrl
? websocket._originalIpc
? opts.socketPath === websocket._originalHostOrSocketPath
: false
: websocket._originalUnixSocket
: websocket._originalIpc
? false
: parsedUrl.host === websocket._originalHostOrSocketPath;

Expand Down
24 changes: 9 additions & 15 deletions test/websocket-server.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,22 +178,16 @@ describe('WebSocketServer', () => {
});
});

it('uses a precreated http server listening on unix socket', function (done) {
//
// Skip this test on Windows. The URL parser:
//
// - Throws an error if the named pipe uses backward slashes.
// - Incorrectly parses the path if the named pipe uses forward slashes.
//
if (process.platform === 'win32') return this.skip();
it('uses a precreated http server listening on IPC', (done) => {
const randomString = crypto.randomBytes(16).toString('hex');
const ipcPath =
process.platform === 'win32'
? `\\\\.\\pipe\\ws-pipe-${randomString}`
: path.join(os.tmpdir(), `ws-${randomString}.sock`);

const server = http.createServer();
const sockPath = path.join(
os.tmpdir(),
`ws.${crypto.randomBytes(16).toString('hex')}.sock`
);

server.listen(sockPath, () => {
server.listen(ipcPath, () => {
const wss = new WebSocket.Server({ server });

wss.on('connection', (ws, req) => {
Expand All @@ -210,8 +204,8 @@ describe('WebSocketServer', () => {
}
});

const ws = new WebSocket(`ws+unix:${sockPath}:/foo?bar=bar`);
ws.on('open', () => new WebSocket(`ws+unix:${sockPath}`));
const ws = new WebSocket(`ws+unix:${ipcPath}:/foo?bar=bar`);
ws.on('open', () => new WebSocket(`ws+unix:${ipcPath}`));
});
});
});
Expand Down
79 changes: 41 additions & 38 deletions test/websocket.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1536,19 +1536,18 @@ describe('WebSocket', () => {
});
});

it('drops the Authorization, Cookie and Host headers (2/4)', function (done) {
if (process.platform === 'win32') return this.skip();

it('drops the Authorization, Cookie and Host headers (2/4)', (done) => {
// Test the `ws:` to `ws+unix:` case.

const socketPath = path.join(
os.tmpdir(),
`ws.${crypto.randomBytes(16).toString('hex')}.sock`
);
const randomString = crypto.randomBytes(16).toString('hex');
const ipcPath =
process.platform === 'win32'
? `\\\\.\\pipe\\ws-pipe-${randomString}`
: path.join(os.tmpdir(), `ws-${randomString}.sock`);

server.once('upgrade', (req, socket) => {
socket.end(
`HTTP/1.1 302 Found\r\nLocation: ws+unix:${socketPath}\r\n\r\n`
`HTTP/1.1 302 Found\r\nLocation: ws+unix:${ipcPath}\r\n\r\n`
);
});

Expand All @@ -1563,7 +1562,7 @@ describe('WebSocket', () => {
ws.close();
});

redirectedServer.listen(socketPath, () => {
redirectedServer.listen(ipcPath, () => {
const headers = {
authorization: 'Basic Zm9vOmJhcg==',
cookie: 'foo=bar',
Expand All @@ -1589,34 +1588,42 @@ describe('WebSocket', () => {

ws.on('close', (code) => {
assert.strictEqual(code, 1005);
assert.strictEqual(ws.url, `ws+unix:${socketPath}`);
assert.strictEqual(ws.url, `ws+unix:${ipcPath}`);
assert.strictEqual(ws._redirects, 1);

redirectedServer.close(done);
});
});
});

it('drops the Authorization, Cookie and Host headers (3/4)', function (done) {
if (process.platform === 'win32') return this.skip();

it('drops the Authorization, Cookie and Host headers (3/4)', (done) => {
// Test the `ws+unix:` to `ws+unix:` case.

const redirectingServerSocketPath = path.join(
os.tmpdir(),
`ws.${crypto.randomBytes(16).toString('hex')}.sock`
);
const redirectedServerSocketPath = path.join(
os.tmpdir(),
`ws.${crypto.randomBytes(16).toString('hex')}.sock`
);
const randomString1 = crypto.randomBytes(16).toString('hex');
const randomString2 = crypto.randomBytes(16).toString('hex');
let redirectingServerIpcPath;
let redirectedServerIpcPath;

if (process.platform === 'win32') {
redirectingServerIpcPath = `\\\\.\\pipe\\ws-pipe-${randomString1}`;
redirectedServerIpcPath = `\\\\.\\pipe\\ws-pipe-${randomString2}`;
} else {
redirectingServerIpcPath = path.join(
os.tmpdir(),
`ws-${randomString1}.sock`
);
redirectedServerIpcPath = path.join(
os.tmpdir(),
`ws-${randomString2}.sock`
);
}

const redirectingServer = http.createServer();

redirectingServer.on('upgrade', (req, socket) => {
socket.end(
'HTTP/1.1 302 Found\r\n' +
`Location: ws+unix:${redirectedServerSocketPath}\r\n\r\n`
`Location: ws+unix:${redirectedServerIpcPath}\r\n\r\n`
);
});

Expand All @@ -1631,8 +1638,8 @@ describe('WebSocket', () => {
ws.close();
});

redirectingServer.listen(redirectingServerSocketPath, listening);
redirectedServer.listen(redirectedServerSocketPath, listening);
redirectingServer.listen(redirectingServerIpcPath, listening);
redirectedServer.listen(redirectedServerIpcPath, listening);

let callCount = 0;

Expand All @@ -1645,7 +1652,7 @@ describe('WebSocket', () => {
host: 'foo'
};

const ws = new WebSocket(`ws+unix:${redirectingServerSocketPath}`, {
const ws = new WebSocket(`ws+unix:${redirectingServerIpcPath}`, {
followRedirects: true,
headers
});
Expand All @@ -1664,10 +1671,7 @@ describe('WebSocket', () => {

ws.on('close', (code) => {
assert.strictEqual(code, 1005);
assert.strictEqual(
ws.url,
`ws+unix:${redirectedServerSocketPath}`
);
assert.strictEqual(ws.url, `ws+unix:${redirectedServerIpcPath}`);
assert.strictEqual(ws._redirects, 1);

redirectingServer.close();
Expand All @@ -1676,9 +1680,7 @@ describe('WebSocket', () => {
}
});

it('drops the Authorization, Cookie and Host headers (4/4)', function (done) {
if (process.platform === 'win32') return this.skip();

it('drops the Authorization, Cookie and Host headers (4/4)', (done) => {
// Test the `ws+unix:` to `ws:` case.

const redirectingServer = http.createServer();
Expand All @@ -1696,12 +1698,13 @@ describe('WebSocket', () => {
ws.close();
});

const socketPath = path.join(
os.tmpdir(),
`ws.${crypto.randomBytes(16).toString('hex')}.sock`
);
const randomString = crypto.randomBytes(16).toString('hex');
const ipcPath =
process.platform === 'win32'
? `\\\\.\\pipe\\ws-pipe-${randomString}`
: path.join(os.tmpdir(), `ws-${randomString}.sock`);

redirectingServer.listen(socketPath, listening);
redirectingServer.listen(ipcPath, listening);
redirectedServer.listen(0, listening);

let callCount = 0;
Expand All @@ -1723,7 +1726,7 @@ describe('WebSocket', () => {
host: 'foo'
};

const ws = new WebSocket(`ws+unix:${socketPath}`, {
const ws = new WebSocket(`ws+unix:${ipcPath}`, {
followRedirects: true,
headers
});
Expand Down