WS test status code support + improved error handing + subprotocol input
This commit is contained in:
parent
271a2d3b35
commit
0bee90ea31
@ -1,6 +1,26 @@
|
||||
const { MonitorType } = require("./monitor-type");
|
||||
const WebSocket = require("ws");
|
||||
const { UP } = require("../../src/util");
|
||||
const { checkStatusCode } = require("../util-server");
|
||||
// Define closing error codes https://www.iana.org/assignments/websocket/websocket.xml#close-code-number
|
||||
const WS_ERR_CODE = {
|
||||
1002: "Protocol error",
|
||||
1003: "Unsupported Data",
|
||||
1005: "No Status Received",
|
||||
1006: "Abnormal Closure",
|
||||
1007: "Invalid frame payload data",
|
||||
1008: "Policy Violation",
|
||||
1009: "Message Too Big",
|
||||
1010: "Mandatory Extension Missing",
|
||||
1011: "Internal Error",
|
||||
1012: "Service Restart",
|
||||
1013: "Try Again Later",
|
||||
1014: "Bad Gateway",
|
||||
1015: "TLS Handshake Failed",
|
||||
3000: "Unauthorized",
|
||||
3003: "Forbidden",
|
||||
3008: "Timeout",
|
||||
};
|
||||
|
||||
class WebSocketMonitorType extends MonitorType {
|
||||
name = "websocket-upgrade";
|
||||
@ -11,24 +31,31 @@ class WebSocketMonitorType extends MonitorType {
|
||||
async check(monitor, heartbeat, _server) {
|
||||
const [ message, code ] = await this.attemptUpgrade(monitor);
|
||||
|
||||
if (code === 1000) {
|
||||
// If no close code, then an error has occurred, display to user
|
||||
if (typeof code === "undefined") {
|
||||
throw new Error(`${message}`);
|
||||
}
|
||||
// If returned status code matches user controlled accepted status code(default 1000), return success
|
||||
if (checkStatusCode(code, JSON.parse(monitor.accepted_statuscodes_json))) {
|
||||
heartbeat.status = UP;
|
||||
heartbeat.msg = message;
|
||||
} else {
|
||||
throw new Error(message);
|
||||
return; //success at this point
|
||||
}
|
||||
|
||||
// Throw an error using friendly name if defined, fallback to generic msg
|
||||
throw new Error(WS_ERR_CODE[code] || `Unexpected status code: ${code}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the builtin Websocket API to establish a connection to target server
|
||||
* Uses the ws Node.js library to establish a connection to target server
|
||||
* @param {object} monitor The monitor object for input parameters.
|
||||
* @returns {[ string, int ]} Array containing a status message and response code
|
||||
*/
|
||||
async attemptUpgrade(monitor) {
|
||||
return new Promise((resolve) => {
|
||||
let ws;
|
||||
//If user selected a subprotocol, sets Sec-WebSocket-Protocol header. Subprotocol Identifier column: https://www.iana.org/assignments/websocket/websocket.xml#subprotocol-name
|
||||
ws = monitor.wsSubprotocol === "" ? new WebSocket(monitor.url) : new WebSocket(monitor.url, monitor.wsSubprotocol);
|
||||
// If user inputs subprotocol(s), convert to array, then set Sec-WebSocket-Protocol header. Subprotocol Identifier column: https://www.iana.org/assignments/websocket/websocket.xml#subprotocol-name
|
||||
ws = !monitor.wsSubprotocol ? new WebSocket(monitor.url) : new WebSocket(monitor.url, monitor.wsSubprotocol.replace(/\s/g, "").split(","));
|
||||
|
||||
ws.addEventListener("open", (event) => {
|
||||
// Immediately close the connection
|
||||
@ -36,7 +63,8 @@ class WebSocketMonitorType extends MonitorType {
|
||||
});
|
||||
|
||||
ws.onerror = (error) => {
|
||||
// Give user the choice to ignore Sec-WebSocket-Accept header
|
||||
// Give user the choice to ignore Sec-WebSocket-Accept header for non compliant servers
|
||||
// Header in HTTP 101 Switching Protocols response from server, technically already upgraded to WS
|
||||
if (monitor.wsIgnoreSecWebsocketAcceptHeader && error.message === "Invalid Sec-WebSocket-Accept header") {
|
||||
resolve([ "101 - OK", 1000 ]);
|
||||
return;
|
||||
@ -46,8 +74,8 @@ class WebSocketMonitorType extends MonitorType {
|
||||
};
|
||||
|
||||
ws.onclose = (event) => {
|
||||
// Upgrade success, connection closed successfully
|
||||
resolve([ "101 - OK", event.code ]);
|
||||
// Return the close code, if connection didn't close cleanly, return the reason if present
|
||||
resolve([ event.wasClean ? event.code.toString() + " - OK" : event.reason, event.code ]);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@ -90,39 +90,9 @@
|
||||
"upsideDownModeDescription": "Flip the status upside down. If the service is reachable, it is DOWN.",
|
||||
"ignoreSecWebsocketAcceptHeaderDescription": "Allows the server to not reply with Sec-WebSocket-Accept header, if the websocket upgrade succeeds.",
|
||||
"Ignore Sec-WebSocket-Accept header": "Ignore {0} header",
|
||||
"wsSubprotocolDescription": "For more information on subprotocols, please consult the {documentation}",
|
||||
"WebSocket Application Messaging Protocol": "WAMP (The WebSocket Application Messaging Protocol)",
|
||||
"Session Initiation Protocol": "WebSocket Transport for SIP (Session Initiation Protocol)",
|
||||
"Subprotocol": "Subprotocol",
|
||||
"Network API for Notification Channel": "OMA RESTful Network API for Notification Channel",
|
||||
"Web Process Control Protocol": "Web Process Control Protocol (WPCP)",
|
||||
"Advanced Message Queuing Protocol": "Advanced Message Queuing Protocol (AMQP) 1.0+",
|
||||
"jsflow": "jsFlow pubsub/queue Protocol",
|
||||
"Reverse Web Process Control": "Reverse Web Process Control Protocol (RWPCP)",
|
||||
"Extensible Messaging and Presence Protocol": "WebSocket Transport for the Extensible Messaging and Presence Protocol (XMPP)",
|
||||
"Smart Home IP": "SHIP - Smart Home IP",
|
||||
"Miele Cloud Connect Protocol": "Miele Cloud Connect Protocol",
|
||||
"Push Channel Protocol": "Push Channel Protocol",
|
||||
"Message Session Relay Protocol": "WebSocket Transport for MSRP (Message Session Relay Protocol)",
|
||||
"Binary Floor Control Protocol": "WebSocket Transport for BFCP (Binary Floor Control Protocol)",
|
||||
"Softvelum Low Delay Protocol": "Softvelum Low Delay Protocol",
|
||||
"OPC UA Connection Protocol": "OPC UA Connection Protocol",
|
||||
"OPC UA JSON Encoding": "OPC UA JSON Encoding",
|
||||
"Swindon Web Server Protocol": "Swindon Web Server Protocol (JSON encoding)",
|
||||
"Broadband Forum User Services Platform": "USP (Broadband Forum User Services Platform)",
|
||||
"Constrained Application Protocol": "Constrained Application Protocol (CoAP)",
|
||||
"Softvelum WebSocket signaling protocol": "Softvelum WebSocket Signaling Protocol",
|
||||
"Cobra Real Time Messaging Protocol": "Cobra Real Time Messaging Protocol",
|
||||
"Declarative Resource Protocol": "Declarative Resource Protocol",
|
||||
"BACnet Secure Connect Hub Connection": "BACnet Secure Connect Hub Connection",
|
||||
"BACnet Secure Connect Direct Connection": "BACnet Secure Connect Direct Connection",
|
||||
"WebSocket Transport for JMAP": "WebSocket Transport for JMAP (JSON Meta Application Protocol)",
|
||||
"ITU-T T.140 Real-Time Text": "ITU-T T.140 Real-Time Text",
|
||||
"Done.best IoT Protocol": "Done.best IoT Protocol",
|
||||
"Collection Update": "The Collection Update Websocket Subprotocol",
|
||||
"Text IRC Protocol": "Text IRC Protocol",
|
||||
"Binary IRC Protocol": "Binary IRC Protocol",
|
||||
"Penguin Statistics Live Protocol v3": "Penguin Statistics Live Protocol v3 (Protobuf encoding)",
|
||||
"wsSubprotocolDescription": "Enter a comma delimited list of subprotocols. For more information on subprotocols, please consult the {documentation}",
|
||||
"wsCodeDescription": "For more information on status codes, please consult {documentation}",
|
||||
"Subprotocol(s)": "Subprotocol(s)",
|
||||
"maxRedirectDescription": "Maximum number of redirects to follow. Set to 0 to disable redirects.",
|
||||
"Upside Down Mode": "Upside Down Mode",
|
||||
"Max. Redirects": "Max. Redirects",
|
||||
|
||||
@ -142,73 +142,8 @@
|
||||
|
||||
<!-- Websocket Subprotocol Docs: https://www.iana.org/assignments/websocket/websocket.xml#subprotocol-name -->
|
||||
<div v-if="monitor.type === 'websocket-upgrade'" class="my-3">
|
||||
<label for="ws_subprotocol" class="form-label">{{ $t("Subprotocol") }}</label>
|
||||
<select id="ws_subprotocol" v-model="monitor.wsSubprotocol" class="form-select">
|
||||
<option value="" selected>{{ $t("None") }}</option>
|
||||
<option value="MBWS.huawei.com">MBWS</option>
|
||||
<option value="MBLWS.huawei.com">MBLWS</option>
|
||||
<option value="soap">soap</option>
|
||||
<option value="wamp">{{ $t("WebSocket Application Messaging Protocol") }}</option>
|
||||
<option value="v10.stomp">STOMP 1.0</option>
|
||||
<option value="v11.stomp">STOMP 1.1</option>
|
||||
<option value="v12.stomp">STOMP 1.2</option>
|
||||
<option value="ocpp1.2">OCPP 1.2</option>
|
||||
<option value="ocpp1.5">OCPP 1.5</option>
|
||||
<option value="ocpp1.6">OCPP 1.6</option>
|
||||
<option value="ocpp2.0">OCPP 2.0</option>
|
||||
<option value="ocpp2.0.1">OCPP 2.0.1</option>
|
||||
<option value="ocpp2.1">OCPP 2.1</option>
|
||||
<option value="rfb">RFB</option>
|
||||
<option value="sip">{{ $t("Session Initiation Protocol") }}</option>
|
||||
<option value="notificationchannel-netapi-rest.openmobilealliance.org">{{ $t("Network API for Notification Channel") }}</option>
|
||||
<option value="wpcp">{{ $t("Web Process Control Protocol") }}</option>
|
||||
<option value="amqp">{{ $t("Advanced Message Queuing Protocol") }}</option>
|
||||
<option value="mqtt">MQTT</option>
|
||||
<option value="jsflow">{{ $t("jsflow") }}</option>
|
||||
<option value="rwpcp">{{ $t("Reverse Web Process Control") }}</option>
|
||||
<option value="xmpp">{{ $t("Extensible Messaging and Presence Protocol") }}</option>
|
||||
<option value="ship">{{ $t("Smart Home IP") }}</option>
|
||||
<option value="mielecloudconnect">{{ $t("Miele Cloud Connect Protocol") }}</option>
|
||||
<option value="v10.pcp.sap.com">{{ $t("Push Channel Protocol") }}</option>
|
||||
<option value="msrp">{{ $t("Message Session Relay Protocol") }}</option>
|
||||
<option value="v1.saltyrtc.org">SaltyRTC 1.0</option>
|
||||
<option value="TLCP-2.0.0.lightstreamer.com">TLCP 2.0.0</option>
|
||||
<option value="bfcp">{{ $t("Binary Floor Control Protocol") }}</option>
|
||||
<option value="sldp.softvelum.com">{{ $t("Softvelum Low Delay Protocol") }}</option>
|
||||
<option value="opcua+uacp">{{ $t("OPC UA Connection Protocol") }}</option>
|
||||
<option value="opcua+uajson">{{ $t("OPC UA JSON Encoding") }}</option>
|
||||
<option value="v1.swindon-lattice+json">{{ $t("Swindon Web Server Protocol") }}</option>
|
||||
<option value="v1.usp">{{ $t("Broadband Forum User Services Platform") }}</option>
|
||||
<option value="mles-websocket">mles-websocket</option>
|
||||
<option value="coap">{{ $t("Constrained Application Protocol") }}</option>
|
||||
<option value="TLCP-2.1.0.lightstreamer.com">TLCP 2.1.0</option>
|
||||
<option value="sqlnet.oracle.com">sqlnet</option>
|
||||
<option value="oneM2M.R2.0.json">oneM2M R2.0 JSON</option>
|
||||
<option value="oneM2M.R2.0.xml">oneM2M R2.0 XML</option>
|
||||
<option value="oneM2M.R2.0.cbor">oneM2M R2.0 CBOR</option>
|
||||
<option value="transit">Transit</option>
|
||||
<option value="2016.serverpush.dash.mpeg.org">MPEG-DASH-ServerPush-23009-6-2017</option>
|
||||
<option value="2018.mmt.mpeg.org">MPEG-MMT-23008-1-2018</option>
|
||||
<option value="clue">clue</option>
|
||||
<option value="webrtc.softvelum.com">{{ $t("Softvelum WebSocket signaling protocol") }}</option>
|
||||
<option value="cobra.v2.json">{{ $t("Cobra Real Time Messaging Protocol") }}</option>
|
||||
<option value="drp">{{ $t("Declarative Resource Protocol") }}</option>
|
||||
<option value="hub.bsc.bacnet.org">{{ $t("BACnet Secure Connect Hub Connection") }}</option>
|
||||
<option value="dc.bsc.bacnet.org">{{ $t("BACnet Secure Connect Direct Connection") }}</option>
|
||||
<option value="jmap">{{ $t("WebSocket Transport for JMAP") }}</option>
|
||||
<option value="t140">{{ $t("ITU-T T.140 Real-Time Text") }}</option>
|
||||
<option value="done">{{ $t("Done.best IoT Protocol") }}</option>
|
||||
<option value="TLCP-2.2.0.lightstreamer.com">TLCP 2.2.0</option>
|
||||
<option value="collection-update">{{ $t("Collection Update") }}</option>
|
||||
<option value="TLCP-2.3.0.lightstreamer.com">TLCP 2.3.0</option>
|
||||
<option value="text.ircv3.net">{{ $t("Text IRC Protocol") }}</option>
|
||||
<option value="binary.ircv3.net">{{ $t("Binary IRC Protocol") }}</option>
|
||||
<option value="v3.penguin-stats.live+proto">{{ $t("Penguin Statistics Live Protocol v3") }}</option>
|
||||
<option value="TLCP-2.4.0.lightstreamer.com">TLCP 2.4.0</option>
|
||||
<option value="TLCP-2.5.0.lightstreamer.com">TLCP 2.5.0</option>
|
||||
<option value="Redfish">Redfish DSP0266</option>
|
||||
<option value="bidib">webBiDiB</option>
|
||||
</select>
|
||||
<label for="ws_subprotocol" class="form-label">{{ $t("Subprotocol(s)") }}</label>
|
||||
<input id="ws_subprotocol" v-model="monitor.wsSubprotocol" type="text" class="form-control" :placeholder="$t('Optional')">
|
||||
<i18n-t tag="div" class="form-text" keypath="wsSubprotocolDescription">
|
||||
<template #documentation>
|
||||
<a href="https://www.iana.org/assignments/websocket/websocket.xml#subprotocol-name" target="_blank" rel="noopener noreferrer">{{ $t('documentationOf', ['IANA']) }}</a>
|
||||
@ -889,6 +824,36 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Websocket Upgrade only -->
|
||||
<template v-if="monitor.type === 'websocket-upgrade' ">
|
||||
<div class="my-3">
|
||||
<label for="acceptedStatusCodes" class="form-label">{{ $t("Accepted Status Codes") }}</label>
|
||||
|
||||
<VueMultiselect
|
||||
id="acceptedStatusCodes"
|
||||
v-model="monitor.accepted_statuscodes"
|
||||
:options="acceptedWebsocketCodeOptions"
|
||||
:multiple="true"
|
||||
:close-on-select="false"
|
||||
:clear-on-select="false"
|
||||
:preserve-search="true"
|
||||
:placeholder="$t('Pick Accepted Status Codes...')"
|
||||
:preselect-first="false"
|
||||
:max-height="600"
|
||||
:taggable="true"
|
||||
></VueMultiselect>
|
||||
|
||||
<div class="form-text">
|
||||
{{ $t("acceptedStatusCodesDescription") }}
|
||||
</div>
|
||||
<i18n-t tag="div" class="form-text" keypath="wsCodeDescription">
|
||||
<template #documentation>
|
||||
<a href="https://datatracker.ietf.org/doc/html/rfc6455#section-7.4" target="_blank" rel="noopener noreferrer">{{ 'RFC6455' }}</a>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- HTTP / Keyword only -->
|
||||
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' || monitor.type === 'json-query' || monitor.type === 'grpc-keyword' ">
|
||||
<div class="my-3">
|
||||
@ -1398,6 +1363,7 @@ export default {
|
||||
},
|
||||
hasDomain: false,
|
||||
acceptedStatusCodeOptions: [],
|
||||
acceptedWebsocketCodeOptions: [],
|
||||
dnsresolvetypeOptions: [],
|
||||
kafkaSaslMechanismOptions: [],
|
||||
ipOrHostnameRegexPattern: hostNameRegexPattern(),
|
||||
@ -1770,6 +1736,7 @@ message HealthCheckResponse {
|
||||
"monitor.type"(newType, oldType) {
|
||||
if (oldType && this.monitor.type === "websocket-upgrade") {
|
||||
this.monitor.url = "wss://";
|
||||
this.monitor.accepted_statuscodes = [ "1000" ];
|
||||
}
|
||||
if (this.monitor.type === "push") {
|
||||
if (! this.monitor.pushToken) {
|
||||
@ -1877,6 +1844,8 @@ message HealthCheckResponse {
|
||||
"500-599",
|
||||
];
|
||||
|
||||
let acceptedWebsocketCodeOptions = [];
|
||||
|
||||
let dnsresolvetypeOptions = [
|
||||
"A",
|
||||
"AAAA",
|
||||
@ -1902,6 +1871,11 @@ message HealthCheckResponse {
|
||||
acceptedStatusCodeOptions.push(i.toString());
|
||||
}
|
||||
|
||||
for (let i = 1000; i <= 4999; i++) {
|
||||
acceptedWebsocketCodeOptions.push(i.toString());
|
||||
}
|
||||
|
||||
this.acceptedWebsocketCodeOptions = acceptedWebsocketCodeOptions;
|
||||
this.acceptedStatusCodeOptions = acceptedStatusCodeOptions;
|
||||
this.dnsresolvetypeOptions = dnsresolvetypeOptions;
|
||||
this.kafkaSaslMechanismOptions = kafkaSaslMechanismOptions;
|
||||
|
||||
@ -6,7 +6,7 @@ const { UP, PENDING } = require("../../src/util");
|
||||
|
||||
describe("Websocket Test", {
|
||||
}, () => {
|
||||
test("Non Websocket Server", {}, async () => {
|
||||
test("Non WS Server", {}, async () => {
|
||||
const websocketMonitor = new WebSocketMonitorType();
|
||||
|
||||
const monitor = {
|
||||
@ -25,12 +25,13 @@ describe("Websocket Test", {
|
||||
);
|
||||
});
|
||||
|
||||
test("Secure Websocket", async () => {
|
||||
test("Secure WS", async () => {
|
||||
const websocketMonitor = new WebSocketMonitorType();
|
||||
|
||||
const monitor = {
|
||||
url: "wss://echo.websocket.org",
|
||||
wsIgnoreSecWebsocketAcceptHeader: false,
|
||||
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
@ -39,7 +40,7 @@ describe("Websocket Test", {
|
||||
};
|
||||
|
||||
const expected = {
|
||||
msg: "101 - OK",
|
||||
msg: "1000 - OK",
|
||||
status: UP,
|
||||
};
|
||||
|
||||
@ -47,7 +48,7 @@ describe("Websocket Test", {
|
||||
assert.deepStrictEqual(heartbeat, expected);
|
||||
});
|
||||
|
||||
test("Insecure Websocket", async (t) => {
|
||||
test("Insecure WS", async (t) => {
|
||||
t.after(() => wss.close());
|
||||
const websocketMonitor = new WebSocketMonitorType();
|
||||
const wss = new WebSocketServer({ port: 8080 });
|
||||
@ -55,6 +56,7 @@ describe("Websocket Test", {
|
||||
const monitor = {
|
||||
url: "ws://localhost:8080",
|
||||
wsIgnoreSecWebsocketAcceptHeader: false,
|
||||
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
@ -63,7 +65,7 @@ describe("Websocket Test", {
|
||||
};
|
||||
|
||||
const expected = {
|
||||
msg: "101 - OK",
|
||||
msg: "1000 - OK",
|
||||
status: UP,
|
||||
};
|
||||
|
||||
@ -71,12 +73,33 @@ describe("Websocket Test", {
|
||||
assert.deepStrictEqual(heartbeat, expected);
|
||||
});
|
||||
|
||||
test("Non compliant WS Server wrong status code", async () => {
|
||||
const websocketMonitor = new WebSocketMonitorType();
|
||||
|
||||
const monitor = {
|
||||
url: "wss://echo.websocket.org",
|
||||
wsIgnoreSecWebsocketAcceptHeader: false,
|
||||
accepted_statuscodes_json: JSON.stringify([ "1001" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
msg: "",
|
||||
status: PENDING,
|
||||
};
|
||||
|
||||
await assert.rejects(
|
||||
websocketMonitor.check(monitor, heartbeat, {}),
|
||||
new Error("Unexpected status code: 1000")
|
||||
);
|
||||
});
|
||||
|
||||
test("Non compliant WS server without IgnoreSecWebsocket", async () => {
|
||||
const websocketMonitor = new WebSocketMonitorType();
|
||||
|
||||
const monitor = {
|
||||
url: "wss://c.img-cdn.net/yE4s7KehTFyj/",
|
||||
wsIgnoreSecWebsocketAcceptHeader: false,
|
||||
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
@ -96,6 +119,7 @@ describe("Websocket Test", {
|
||||
const monitor = {
|
||||
url: "wss://c.img-cdn.net/yE4s7KehTFyj/",
|
||||
wsIgnoreSecWebsocketAcceptHeader: true,
|
||||
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
@ -104,7 +128,7 @@ describe("Websocket Test", {
|
||||
};
|
||||
|
||||
const expected = {
|
||||
msg: "101 - OK",
|
||||
msg: "1000 - OK",
|
||||
status: UP,
|
||||
};
|
||||
|
||||
@ -118,6 +142,7 @@ describe("Websocket Test", {
|
||||
const monitor = {
|
||||
url: "wss://echo.websocket.org",
|
||||
wsIgnoreSecWebsocketAcceptHeader: true,
|
||||
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
@ -126,7 +151,7 @@ describe("Websocket Test", {
|
||||
};
|
||||
|
||||
const expected = {
|
||||
msg: "101 - OK",
|
||||
msg: "1000 - OK",
|
||||
status: UP,
|
||||
};
|
||||
|
||||
@ -140,6 +165,7 @@ describe("Websocket Test", {
|
||||
const monitor = {
|
||||
url: "wss://example.org",
|
||||
wsIgnoreSecWebsocketAcceptHeader: true,
|
||||
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
@ -153,13 +179,14 @@ describe("Websocket Test", {
|
||||
);
|
||||
});
|
||||
|
||||
test("Secure Websocket with Subprotocol", async () => {
|
||||
test("Secure WS no support one subprotocol", async () => {
|
||||
const websocketMonitor = new WebSocketMonitorType();
|
||||
|
||||
const monitor = {
|
||||
url: "wss://echo.websocket.org",
|
||||
wsIgnoreSecWebsocketAcceptHeader: false,
|
||||
wsSubprotocol: "ocpp1.6",
|
||||
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
@ -172,4 +199,55 @@ describe("Websocket Test", {
|
||||
new Error("Server sent no subprotocol")
|
||||
);
|
||||
});
|
||||
|
||||
test("Multiple subprotocols bad input", async () => {
|
||||
const websocketMonitor = new WebSocketMonitorType();
|
||||
|
||||
const monitor = {
|
||||
url: "wss://echo.websocket.org",
|
||||
wsIgnoreSecWebsocketAcceptHeader: false,
|
||||
wsSubprotocol: " ocpp2.0 , ocpp1.6 , ",
|
||||
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
msg: "",
|
||||
status: PENDING,
|
||||
};
|
||||
|
||||
await assert.rejects(
|
||||
websocketMonitor.check(monitor, heartbeat, {}),
|
||||
new SyntaxError("An invalid or duplicated subprotocol was specified")
|
||||
);
|
||||
});
|
||||
|
||||
test("Insecure WS support one subprotocol", async (t) => {
|
||||
t.after(() => wss.close());
|
||||
const websocketMonitor = new WebSocketMonitorType();
|
||||
const wss = new WebSocketServer({ port: 8080,
|
||||
handleProtocols: (protocols) => {
|
||||
return Array.from(protocols).includes("test") ? "test" : null;
|
||||
}
|
||||
});
|
||||
|
||||
const monitor = {
|
||||
url: "ws://localhost:8080",
|
||||
wsIgnoreSecWebsocketAcceptHeader: false,
|
||||
wsSubprotocol: "invalid,test",
|
||||
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
|
||||
};
|
||||
|
||||
const heartbeat = {
|
||||
msg: "",
|
||||
status: PENDING,
|
||||
};
|
||||
|
||||
const expected = {
|
||||
msg: "1000 - OK",
|
||||
status: UP,
|
||||
};
|
||||
|
||||
await websocketMonitor.check(monitor, heartbeat, {});
|
||||
assert.deepStrictEqual(heartbeat, expected);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user