Skip to content

Commit

Permalink
feat: allow username and password in clientURL (#3452)
Browse files Browse the repository at this point in the history
  • Loading branch information
anshumanv committed Jun 18, 2021
1 parent 307f2e7 commit a7225d5
Show file tree
Hide file tree
Showing 20 changed files with 588 additions and 24 deletions.
30 changes: 30 additions & 0 deletions bin/cli-flags.js
Expand Up @@ -275,6 +275,36 @@ module.exports = {
multiple: false,
simpleType: 'string',
},
'client-web-socket-url-username': {
configs: [
{
type: 'string',
multiple: false,
description:
'Tells clients connected to devServer to use the provided username to authenticate.',
path: 'client.webSocketURL.username',
},
],
description:
'Tells clients connected to devServer to use the provided username to authenticate.',
simpleType: 'string',
multiple: false,
},
'client-web-socket-url-password': {
configs: [
{
type: 'string',
multiple: false,
description:
'Tells clients connected to devServer to use the provided password to authenticate.',
path: 'client.webSocketURL.password',
},
],
description:
'Tells clients connected to devServer to use the provided password to authenticate.',
simpleType: 'string',
multiple: false,
},
'web-socket-server': {
configs: [
{
Expand Down
8 changes: 8 additions & 0 deletions lib/options.json
Expand Up @@ -154,6 +154,10 @@
"description": "Tells clients connected to devServer to use the provided path to connect.",
"type": "string"
},
"password": {
"description": "Tells clients connected to devServer to use the provided password to authenticate.",
"type": "string"
},
"port": {
"description": "Tells clients connected to devServer to use the provided port.",
"anyOf": [
Expand All @@ -177,6 +181,10 @@
"minLength": 1
}
]
},
"username": {
"description": "Tells clients connected to devServer to use the provided username to authenticate.",
"type": "string"
}
}
}
Expand Down
34 changes: 23 additions & 11 deletions lib/utils/DevServerPlugin.js
Expand Up @@ -93,6 +93,7 @@ class DevServerPlugin {
if (typeof options.client.webSocketURL.path !== 'undefined') {
path = options.client.webSocketURL.path;
}

// Web socket server works on custom `path`
else if (
typeof options.webSocketServer.options.prefix !== 'undefined' ||
Expand All @@ -103,24 +104,35 @@ class DevServerPlugin {
options.webSocketServer.options.path;
}

/** @type {Record<string, any>} */
const searchParams = {};
/** @type {string} */
let username = '';

if (typeof options.client.webSocketURL.username !== 'undefined') {
username = options.client.webSocketURL.username;
}

/** @type {string} */
let password = '';

if (typeof options.client.webSocketURL.password !== 'undefined') {
password = options.client.webSocketURL.password;
}

const searchParams = new URLSearchParams();

if (typeof options.client.logging !== 'undefined') {
searchParams.logging = options.client.logging;
searchParams.set('logging', options.client.logging);
}

const searchParamsString = searchParams.toString();

return encodeURIComponent(
new URL(
`${protocol}//${ipaddr.IPv6.isIPv6(host) ? `[${host}]` : host}${
`${protocol}//${username}${password ? `:${password}` : ''}${
username || password ? `@` : ''
}${ipaddr.IPv6.isIPv6(host) ? `[${host}]` : host}${
port ? `:${port}` : ''
}${path || '/'}${
Object.keys(searchParams).length > 0
? `?${Object.entries(searchParams)
.map(([key, value]) => `${key}=${value}`)
.join('&')}`
: ''
}`
}${path || '/'}${searchParamsString ? `?${searchParamsString}` : ''}`
).toString()
).replace(
/[!'()*]/g,
Expand Down
2 changes: 2 additions & 0 deletions lib/utils/normalizeOptions.js
Expand Up @@ -124,6 +124,8 @@ function normalizeOptions(compiler, options, logger) {
host: parsedURL.hostname,
port: parsedURL.port.length > 0 ? Number(parsedURL.port) : '',
path: parsedURL.pathname,
username: parsedURL.username,
password: parsedURL.password,
};
} else if (typeof options.client.webSocketURL.port === 'string') {
options.client.webSocketURL.port = Number(options.client.webSocketURL.port);
Expand Down
14 changes: 13 additions & 1 deletion test/__snapshots__/validate-options.test.js.snap.webpack4
Expand Up @@ -172,7 +172,7 @@ exports[`options validate should throw an error on the "client" option with '{"w
exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":true}}' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client.webSocketURL should be one of these:
non-empty string | object { host?, path?, port?, protocol? }
non-empty string | object { host?, path?, password?, port?, protocol?, username? }
-> 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).
Details:
* options.client.webSocketURL.port should be one of these:
Expand All @@ -183,6 +183,18 @@ exports[`options validate should throw an error on the "client" option with '{"w
* options.client.webSocketURL.port should be a non-empty string."
`;

exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"username":123,"password":976}}' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client.webSocketURL should be one of these:
non-empty string | object { host?, path?, password?, port?, protocol?, username? }
-> 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).
Details:
* options.client.webSocketURL.password should be a string.
-> Tells clients connected to devServer to use the provided password to authenticate.
* options.client.webSocketURL.username should be a string.
-> Tells clients connected to devServer to use the provided username to authenticate."
`;

exports[`options validate should throw an error on the "client" option with 'whoops!' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client should be an object:
Expand Down
14 changes: 13 additions & 1 deletion test/__snapshots__/validate-options.test.js.snap.webpack5
Expand Up @@ -172,7 +172,7 @@ exports[`options validate should throw an error on the "client" option with '{"w
exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"port":true}}' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client.webSocketURL should be one of these:
non-empty string | object { host?, path?, port?, protocol? }
non-empty string | object { host?, path?, password?, port?, protocol?, username? }
-> 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).
Details:
* options.client.webSocketURL.port should be one of these:
Expand All @@ -183,6 +183,18 @@ exports[`options validate should throw an error on the "client" option with '{"w
* options.client.webSocketURL.port should be a non-empty string."
`;

exports[`options validate should throw an error on the "client" option with '{"webSocketURL":{"username":123,"password":976}}' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client.webSocketURL should be one of these:
non-empty string | object { host?, path?, password?, port?, protocol?, username? }
-> 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).
Details:
* options.client.webSocketURL.password should be a string.
-> Tells clients connected to devServer to use the provided password to authenticate.
* options.client.webSocketURL.username should be a string.
-> Tells clients connected to devServer to use the provided username to authenticate."
`;

exports[`options validate should throw an error on the "client" option with 'whoops!' value 1`] = `
"ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options.client should be an object:
Expand Down
2 changes: 2 additions & 0 deletions test/cli/__snapshots__/cli.test.js.snap.webpack4
Expand Up @@ -73,6 +73,8 @@ Options:
--client-web-socket-url-port <value> Tells clients connected to devServer to use the provided port.
--client-web-socket-url-path <value> Tells clients connected to devServer to use the provided path to connect.
--client-web-socket-url-protocol <value> Tells clients connected to devServer to use the provided protocol.
--client-web-socket-url-username <value> Tells clients connected to devServer to use the provided username to authenticate.
--client-web-socket-url-password <value> Tells clients connected to devServer to use the provided password to authenticate.
--web-socket-server <value> Allows to set web socket server and options (by default 'ws'). https://webpack.js.org/configuration/dev-server/#devserverwebsocketserver
--compress Enables gzip compression for everything served. https://webpack.js.org/configuration/dev-server/#devservercompress
--no-compress Disables gzip compression for everything served.
Expand Down
2 changes: 2 additions & 0 deletions test/cli/__snapshots__/cli.test.js.snap.webpack5
Expand Up @@ -72,8 +72,10 @@ Options:
--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).
--client-web-socket-url-host <value> Tells clients connected to devServer to use the provided host.
--client-web-socket-url-path <value> Tells clients connected to devServer to use the provided path to connect.
--client-web-socket-url-password <value> Tells clients connected to devServer to use the provided password to authenticate.
--client-web-socket-url-port <value> Tells clients connected to devServer to use the provided port.
--client-web-socket-url-protocol <value> Tells clients connected to devServer to use the provided protocol.
--client-web-socket-url-username <value> Tells clients connected to devServer to use the provided username to authenticate.
--compress Enables gzip compression for everything served. https://webpack.js.org/configuration/dev-server/#devservercompress
--no-compress Negative 'compress' option.
--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
Expand Down
66 changes: 66 additions & 0 deletions test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack4
Expand Up @@ -261,6 +261,28 @@ Array [

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

exports[`web socket server URL should work with the "client.webSocketURL.password" option ("sockjs"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.password" option ("ws"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.path" option ("sockjs"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
Expand Down Expand Up @@ -436,3 +458,47 @@ Array [
`;

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 []`;

exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.username" option ("sockjs"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.username" option ("sockjs"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.username" option ("ws"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.username" option ("ws"): page errors 1`] = `Array []`;
66 changes: 66 additions & 0 deletions test/e2e/__snapshots__/web-socket-server-url.test.js.snap.webpack5
Expand Up @@ -261,6 +261,28 @@ Array [

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

exports[`web socket server URL should work with the "client.webSocketURL.password" option ("sockjs"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.password" option ("ws"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.path" option ("sockjs"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
Expand Down Expand Up @@ -436,3 +458,47 @@ Array [
`;

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 []`;

exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("sockjs"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.username" and "client.webSocketURL.password" option ("ws"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.username" option ("sockjs"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.username" option ("sockjs"): page errors 1`] = `Array []`;

exports[`web socket server URL should work with the "client.webSocketURL.username" option ("ws"): console messages 1`] = `
Array [
"[HMR] Waiting for update signal from WDS...",
"Hey.",
"[webpack-dev-server] Hot Module Replacement enabled.",
"[webpack-dev-server] Live Reloading enabled.",
]
`;

exports[`web socket server URL should work with the "client.webSocketURL.username" option ("ws"): page errors 1`] = `Array []`;

0 comments on commit a7225d5

Please sign in to comment.