Skip to content

Commit a7225d5

Browse files
authored
feat: allow username and password in clientURL (#3452)
1 parent 307f2e7 commit a7225d5

20 files changed

+588
-24
lines changed

bin/cli-flags.js

+30
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,36 @@ module.exports = {
275275
multiple: false,
276276
simpleType: 'string',
277277
},
278+
'client-web-socket-url-username': {
279+
configs: [
280+
{
281+
type: 'string',
282+
multiple: false,
283+
description:
284+
'Tells clients connected to devServer to use the provided username to authenticate.',
285+
path: 'client.webSocketURL.username',
286+
},
287+
],
288+
description:
289+
'Tells clients connected to devServer to use the provided username to authenticate.',
290+
simpleType: 'string',
291+
multiple: false,
292+
},
293+
'client-web-socket-url-password': {
294+
configs: [
295+
{
296+
type: 'string',
297+
multiple: false,
298+
description:
299+
'Tells clients connected to devServer to use the provided password to authenticate.',
300+
path: 'client.webSocketURL.password',
301+
},
302+
],
303+
description:
304+
'Tells clients connected to devServer to use the provided password to authenticate.',
305+
simpleType: 'string',
306+
multiple: false,
307+
},
278308
'web-socket-server': {
279309
configs: [
280310
{

lib/options.json

+8
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@
154154
"description": "Tells clients connected to devServer to use the provided path to connect.",
155155
"type": "string"
156156
},
157+
"password": {
158+
"description": "Tells clients connected to devServer to use the provided password to authenticate.",
159+
"type": "string"
160+
},
157161
"port": {
158162
"description": "Tells clients connected to devServer to use the provided port.",
159163
"anyOf": [
@@ -177,6 +181,10 @@
177181
"minLength": 1
178182
}
179183
]
184+
},
185+
"username": {
186+
"description": "Tells clients connected to devServer to use the provided username to authenticate.",
187+
"type": "string"
180188
}
181189
}
182190
}

lib/utils/DevServerPlugin.js

+23-11
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class DevServerPlugin {
9393
if (typeof options.client.webSocketURL.path !== 'undefined') {
9494
path = options.client.webSocketURL.path;
9595
}
96+
9697
// Web socket server works on custom `path`
9798
else if (
9899
typeof options.webSocketServer.options.prefix !== 'undefined' ||
@@ -103,24 +104,35 @@ class DevServerPlugin {
103104
options.webSocketServer.options.path;
104105
}
105106

106-
/** @type {Record<string, any>} */
107-
const searchParams = {};
107+
/** @type {string} */
108+
let username = '';
109+
110+
if (typeof options.client.webSocketURL.username !== 'undefined') {
111+
username = options.client.webSocketURL.username;
112+
}
113+
114+
/** @type {string} */
115+
let password = '';
116+
117+
if (typeof options.client.webSocketURL.password !== 'undefined') {
118+
password = options.client.webSocketURL.password;
119+
}
120+
121+
const searchParams = new URLSearchParams();
108122

109123
if (typeof options.client.logging !== 'undefined') {
110-
searchParams.logging = options.client.logging;
124+
searchParams.set('logging', options.client.logging);
111125
}
112126

127+
const searchParamsString = searchParams.toString();
128+
113129
return encodeURIComponent(
114130
new URL(
115-
`${protocol}//${ipaddr.IPv6.isIPv6(host) ? `[${host}]` : host}${
131+
`${protocol}//${username}${password ? `:${password}` : ''}${
132+
username || password ? `@` : ''
133+
}${ipaddr.IPv6.isIPv6(host) ? `[${host}]` : host}${
116134
port ? `:${port}` : ''
117-
}${path || '/'}${
118-
Object.keys(searchParams).length > 0
119-
? `?${Object.entries(searchParams)
120-
.map(([key, value]) => `${key}=${value}`)
121-
.join('&')}`
122-
: ''
123-
}`
135+
}${path || '/'}${searchParamsString ? `?${searchParamsString}` : ''}`
124136
).toString()
125137
).replace(
126138
/[!'()*]/g,

lib/utils/normalizeOptions.js

+2
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ function normalizeOptions(compiler, options, logger) {
124124
host: parsedURL.hostname,
125125
port: parsedURL.port.length > 0 ? Number(parsedURL.port) : '',
126126
path: parsedURL.pathname,
127+
username: parsedURL.username,
128+
password: parsedURL.password,
127129
};
128130
} else if (typeof options.client.webSocketURL.port === 'string') {
129131
options.client.webSocketURL.port = Number(options.client.webSocketURL.port);

test/__snapshots__/validate-options.test.js.snap.webpack4

+13-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ exports[`options validate should throw an error on the "client" option with '{"w
172172
exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":true}}' value 1`] = `
173173
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
174174
- options.client.webSocketURL should be one of these:
175-
non-empty string | object { host?, path?, port?, protocol? }
175+
non-empty string | object { host?, path?, password?, port?, protocol?, username? }
176176
-> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to).
177177
Details:
178178
* options.client.webSocketURL.port should be one of these:
@@ -183,6 +183,18 @@ exports[`options validate should throw an error on the "client" option with '{"w
183183
* options.client.webSocketURL.port should be a non-empty string."
184184
`;
185185

186+
exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"username":123,"password":976}}' value 1`] = `
187+
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
188+
- options.client.webSocketURL should be one of these:
189+
non-empty string | object { host?, path?, password?, port?, protocol?, username? }
190+
-> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to).
191+
Details:
192+
* options.client.webSocketURL.password should be a string.
193+
-> Tells clients connected to devServer to use the provided password to authenticate.
194+
* options.client.webSocketURL.username should be a string.
195+
-> Tells clients connected to devServer to use the provided username to authenticate."
196+
`;
197+
186198
exports[`options validate should throw an error on the "client" option with 'whoops!' value 1`] = `
187199
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
188200
- options.client should be an object:

test/__snapshots__/validate-options.test.js.snap.webpack5

+13-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ exports[`options validate should throw an error on the "client" option with '{"w
172172
exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":true}}' value 1`] = `
173173
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
174174
- options.client.webSocketURL should be one of these:
175-
non-empty string | object { host?, path?, port?, protocol? }
175+
non-empty string | object { host?, path?, password?, port?, protocol?, username? }
176176
-> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to).
177177
Details:
178178
* options.client.webSocketURL.port should be one of these:
@@ -183,6 +183,18 @@ exports[`options validate should throw an error on the "client" option with '{"w
183183
* options.client.webSocketURL.port should be a non-empty string."
184184
`;
185185

186+
exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"username":123,"password":976}}' value 1`] = `
187+
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
188+
- options.client.webSocketURL should be one of these:
189+
non-empty string | object { host?, path?, password?, port?, protocol?, username? }
190+
-> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to).
191+
Details:
192+
* options.client.webSocketURL.password should be a string.
193+
-> Tells clients connected to devServer to use the provided password to authenticate.
194+
* options.client.webSocketURL.username should be a string.
195+
-> Tells clients connected to devServer to use the provided username to authenticate."
196+
`;
197+
186198
exports[`options validate should throw an error on the "client" option with 'whoops!' value 1`] = `
187199
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
188200
- options.client should be an object:

test/cli/__snapshots__/cli.test.js.snap.webpack4

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ Options:
7373
--client-web-socket-url-port <value> Tells clients connected to devServer to use the provided port.
7474
--client-web-socket-url-path <value> Tells clients connected to devServer to use the provided path to connect.
7575
--client-web-socket-url-protocol <value> Tells clients connected to devServer to use the provided protocol.
76+
--client-web-socket-url-username <value> Tells clients connected to devServer to use the provided username to authenticate.
77+
--client-web-socket-url-password <value> Tells clients connected to devServer to use the provided password to authenticate.
7678
--web-socket-server <value> Allows to set web socket server and options (by default 'ws'). https://webpack.js.org/configuration/dev-server/#devserverwebsocketserver
7779
--compress Enables gzip compression for everything served. https://webpack.js.org/configuration/dev-server/#devservercompress
7880
--no-compress Disables gzip compression for everything served.

test/cli/__snapshots__/cli.test.js.snap.webpack5

+2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ Options:
7272
--client-web-socket-url <value> Allows to specify URL to web socket server (useful when you're proxying dev server and client script does not always know where to connect to).
7373
--client-web-socket-url-host <value> Tells clients connected to devServer to use the provided host.
7474
--client-web-socket-url-path <value> Tells clients connected to devServer to use the provided path to connect.
75+
--client-web-socket-url-password <value> Tells clients connected to devServer to use the provided password to authenticate.
7576
--client-web-socket-url-port <value> Tells clients connected to devServer to use the provided port.
7677
--client-web-socket-url-protocol <value> Tells clients connected to devServer to use the provided protocol.
78+
--client-web-socket-url-username <value> Tells clients connected to devServer to use the provided username to authenticate.
7779
--compress Enables gzip compression for everything served. https://webpack.js.org/configuration/dev-server/#devservercompress
7880
--no-compress Negative 'compress' option.
7981
--history-api-fallback Allows to proxy requests through a specified index page (by default 'index.html'), useful for Single Page Applications that utilise the HTML5 History API. https://webpack.js.org/configuration/dev-server/#devserverhistoryapifallback

test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack4

+66
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,28 @@ Array [
261261

262262
exports[`web socket server URL should work with the "client.webSocketURL.host" option using "0.0.0.0" value ("ws"): page errors 1`] = `Array []`;
263263

264+
exports[`web socket server URL should work with the "client.webSocketURL.password" option ("sockjs"): console messages 1`] = `
265+
Array [
266+
"[HMR] Waiting for update signal from WDS...",
267+
"Hey.",
268+
"[webpack-dev-server] Hot Module Replacement enabled.",
269+
"[webpack-dev-server] Live Reloading enabled.",
270+
]
271+
`;
272+
273+
exports[`web socket server URL should work with the "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`;
274+
275+
exports[`web socket server URL should work with the "client.webSocketURL.password" option ("ws"): console messages 1`] = `
276+
Array [
277+
"[HMR] Waiting for update signal from WDS...",
278+
"Hey.",
279+
"[webpack-dev-server] Hot Module Replacement enabled.",
280+
"[webpack-dev-server] Live Reloading enabled.",
281+
]
282+
`;
283+
284+
exports[`web socket server URL should work with the "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`;
285+
264286
exports[`web socket server URL should work with the "client.webSocketURL.path" option ("sockjs"): console messages 1`] = `
265287
Array [
266288
"[HMR] Waiting for update signal from WDS...",
@@ -436,3 +458,47 @@ Array [
436458
`;
437459

438460
exports[`web socket server URL should work with the "client.webSocketURL.protocol" option using "http:" value and covert to "ws:" ("ws"): page errors 1`] = `Array []`;
461+
462+
exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): console messages 1`] = `
463+
Array [
464+
"[HMR] Waiting for update signal from WDS...",
465+
"Hey.",
466+
"[webpack-dev-server] Hot Module Replacement enabled.",
467+
"[webpack-dev-server] Live Reloading enabled.",
468+
]
469+
`;
470+
471+
exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`;
472+
473+
exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): console messages 1`] = `
474+
Array [
475+
"[HMR] Waiting for update signal from WDS...",
476+
"Hey.",
477+
"[webpack-dev-server] Hot Module Replacement enabled.",
478+
"[webpack-dev-server] Live Reloading enabled.",
479+
]
480+
`;
481+
482+
exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`;
483+
484+
exports[`web socket server URL should work with the "client.webSocketURL.username" option ("sockjs"): console messages 1`] = `
485+
Array [
486+
"[HMR] Waiting for update signal from WDS...",
487+
"Hey.",
488+
"[webpack-dev-server] Hot Module Replacement enabled.",
489+
"[webpack-dev-server] Live Reloading enabled.",
490+
]
491+
`;
492+
493+
exports[`web socket server URL should work with the "client.webSocketURL.username" option ("sockjs"): page errors 1`] = `Array []`;
494+
495+
exports[`web socket server URL should work with the "client.webSocketURL.username" option ("ws"): console messages 1`] = `
496+
Array [
497+
"[HMR] Waiting for update signal from WDS...",
498+
"Hey.",
499+
"[webpack-dev-server] Hot Module Replacement enabled.",
500+
"[webpack-dev-server] Live Reloading enabled.",
501+
]
502+
`;
503+
504+
exports[`web socket server URL should work with the "client.webSocketURL.username" option ("ws"): page errors 1`] = `Array []`;

test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack5

+66
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,28 @@ Array [
261261

262262
exports[`web socket server URL should work with the "client.webSocketURL.host" option using "0.0.0.0" value ("ws"): page errors 1`] = `Array []`;
263263

264+
exports[`web socket server URL should work with the "client.webSocketURL.password" option ("sockjs"): console messages 1`] = `
265+
Array [
266+
"[HMR] Waiting for update signal from WDS...",
267+
"Hey.",
268+
"[webpack-dev-server] Hot Module Replacement enabled.",
269+
"[webpack-dev-server] Live Reloading enabled.",
270+
]
271+
`;
272+
273+
exports[`web socket server URL should work with the "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`;
274+
275+
exports[`web socket server URL should work with the "client.webSocketURL.password" option ("ws"): console messages 1`] = `
276+
Array [
277+
"[HMR] Waiting for update signal from WDS...",
278+
"Hey.",
279+
"[webpack-dev-server] Hot Module Replacement enabled.",
280+
"[webpack-dev-server] Live Reloading enabled.",
281+
]
282+
`;
283+
284+
exports[`web socket server URL should work with the "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`;
285+
264286
exports[`web socket server URL should work with the "client.webSocketURL.path" option ("sockjs"): console messages 1`] = `
265287
Array [
266288
"[HMR] Waiting for update signal from WDS...",
@@ -436,3 +458,47 @@ Array [
436458
`;
437459

438460
exports[`web socket server URL should work with the "client.webSocketURL.protocol" option using "http:" value and covert to "ws:" ("ws"): page errors 1`] = `Array []`;
461+
462+
exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): console messages 1`] = `
463+
Array [
464+
"[HMR] Waiting for update signal from WDS...",
465+
"Hey.",
466+
"[webpack-dev-server] Hot Module Replacement enabled.",
467+
"[webpack-dev-server] Live Reloading enabled.",
468+
]
469+
`;
470+
471+
exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`;
472+
473+
exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): console messages 1`] = `
474+
Array [
475+
"[HMR] Waiting for update signal from WDS...",
476+
"Hey.",
477+
"[webpack-dev-server] Hot Module Replacement enabled.",
478+
"[webpack-dev-server] Live Reloading enabled.",
479+
]
480+
`;
481+
482+
exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`;
483+
484+
exports[`web socket server URL should work with the "client.webSocketURL.username" option ("sockjs"): console messages 1`] = `
485+
Array [
486+
"[HMR] Waiting for update signal from WDS...",
487+
"Hey.",
488+
"[webpack-dev-server] Hot Module Replacement enabled.",
489+
"[webpack-dev-server] Live Reloading enabled.",
490+
]
491+
`;
492+
493+
exports[`web socket server URL should work with the "client.webSocketURL.username" option ("sockjs"): page errors 1`] = `Array []`;
494+
495+
exports[`web socket server URL should work with the "client.webSocketURL.username" option ("ws"): console messages 1`] = `
496+
Array [
497+
"[HMR] Waiting for update signal from WDS...",
498+
"Hey.",
499+
"[webpack-dev-server] Hot Module Replacement enabled.",
500+
"[webpack-dev-server] Live Reloading enabled.",
501+
]
502+
`;
503+
504+
exports[`web socket server URL should work with the "client.webSocketURL.username" option ("ws"): page errors 1`] = `Array []`;

0 commit comments

Comments
 (0)