EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
test-canvas-endpoint.js
Go to the documentation of this file.
1#!/usr/bin/env node
2/**
3 * Test script for custom canvas desktop endpoint
4 * Tests WebSocket connection and JWT authentication
5 *
6 * Usage:
7 * node test-canvas-endpoint.js <jwt_token> <node_id> [meshcentral_url]
8 *
9 * Example:
10 * node test-canvas-endpoint.js "eyJhbGc..." "node123" "wss://meshcentral.domain.com"
11 */
12
13const WebSocket = require('ws');
14
15// Parse command line arguments
16const args = process.argv.slice(2);
17if (args.length < 2) {
18 console.log('Usage: node test-canvas-endpoint.js <jwt_token> <node_id> [meshcentral_url]');
19 console.log('');
20 console.log('Arguments:');
21 console.log(' jwt_token - JWT token from dashboard login');
22 console.log(' node_id - MeshCentral node ID (agent identifier)');
23 console.log(' meshcentral_url - Optional: MeshCentral WebSocket URL');
24 console.log(' Default: wss://rmm-psa-meshcentral-aq48h.ondigitalocean.app');
25 console.log('');
26 console.log('Example:');
27 console.log(' node test-canvas-endpoint.js "eyJhbGc..." "node//abc123..."');
28 process.exit(1);
29}
30
31const token = args[0];
32const nodeId = args[1];
33const baseUrl = args[2] || 'wss://rmm-psa-meshcentral-aq48h.ondigitalocean.app';
34
35// Construct URL
36const wsUrl = `${baseUrl}/api/canvas-desktop/${encodeURIComponent(nodeId)}?token=${encodeURIComponent(token)}`;
37
38console.log('========================================');
39console.log('Canvas Desktop Endpoint Test');
40console.log('========================================');
41console.log('');
42console.log('Configuration:');
43console.log(` Node ID: ${nodeId}`);
44console.log(` Token: ${token.substring(0, 30)}...`);
45console.log(` URL: ${baseUrl}`);
46console.log('');
47console.log('Connecting...');
48console.log('');
49
50// Create WebSocket connection
51const ws = new WebSocket(wsUrl, {
52 rejectUnauthorized: false // Accept self-signed certificates (dev/staging only)
53});
54
55let pingInterval;
56let messageCount = 0;
57
58ws.on('open', () => {
59 console.log('✅ WebSocket connection OPENED');
60 console.log('');
61
62 // Send initial ping
63 console.log('📤 Sending ping...');
64 ws.send(JSON.stringify({ type: 'ping', timestamp: Date.now() }));
65
66 // Setup ping interval to keep connection alive
67 pingInterval = setInterval(() => {
68 if (ws.readyState === WebSocket.OPEN) {
69 console.log('📤 Sending periodic ping...');
70 ws.send(JSON.stringify({ type: 'ping', timestamp: Date.now() }));
71 }
72 }, 10000); // Ping every 10 seconds
73});
74
75ws.on('message', (data) => {
76 messageCount++;
77 try {
78 const msg = JSON.parse(data.toString());
79 console.log(`📨 Message ${messageCount} received:`, JSON.stringify(msg, null, 2));
80 console.log('');
81
82 // If this is a pong response, calculate latency
83 if (msg.type === 'pong' && msg.timestamp) {
84 const latency = Date.now() - msg.timestamp;
85 console.log(`⚡ Latency: ${latency}ms`);
86 console.log('');
87 }
88
89 // If connected successfully, show capabilities
90 if (msg.type === 'connected') {
91 console.log('🎉 Connection Successful!');
92 console.log('');
93 console.log('Connection Details:');
94 console.log(` Node ID: ${msg.nodeId}`);
95 console.log(` User ID: ${msg.userId}`);
96 console.log(` Tenant ID: ${msg.tenantId}`);
97 console.log(` Phase: ${msg.phase}`);
98 console.log(` Capabilities: ${msg.capabilities?.join(', ')}`);
99 console.log(` Message: ${msg.message}`);
100 console.log('');
101 }
102
103 } catch (err) {
104 console.error('❌ Error parsing message:', err.message);
105 console.error(' Raw data:', data.toString());
106 console.log('');
107 }
108});
109
110ws.on('error', (err) => {
111 console.error('❌ WebSocket ERROR:', err.message);
112 console.log('');
113
114 // Common errors and solutions
115 if (err.message.includes('ENOTFOUND')) {
116 console.log('💡 Troubleshooting: Cannot resolve hostname');
117 console.log(' - Check if MeshCentral URL is correct');
118 console.log(' - Verify DNS resolution');
119 } else if (err.message.includes('ECONNREFUSED')) {
120 console.log('💡 Troubleshooting: Connection refused');
121 console.log(' - Check if MeshCentral is running');
122 console.log(' - Verify the port is correct');
123 } else if (err.message.includes('401') || err.message.includes('403')) {
124 console.log('💡 Troubleshooting: Authentication failed');
125 console.log(' - Check if JWT token is valid');
126 console.log(' - Verify token has not expired');
127 console.log(' - Ensure JWT_SECRET matches between backend and MeshCentral');
128 }
129 console.log('');
130});
131
132ws.on('close', (code, reason) => {
133 clearInterval(pingInterval);
134 console.log(`🔌 WebSocket CLOSED`);
135 console.log(` Code: ${code}`);
136 console.log(` Reason: ${reason || 'No reason provided'}`);
137 console.log('');
138 console.log(`Total messages received: ${messageCount}`);
139 console.log('');
140
141 // Explain close codes
142 if (code === 1000) {
143 console.log('✅ Normal closure (successful test)');
144 } else if (code === 1006) {
145 console.log('⚠️ Abnormal closure (connection lost without close frame)');
146 } else if (code === 1008) {
147 console.log('❌ Policy violation (likely authentication failed)');
148 } else if (code === 1011) {
149 console.log('❌ Server error');
150 }
151
152 process.exit(code === 1000 ? 0 : 1);
153});
154
155// Handle Ctrl+C gracefully
156process.on('SIGINT', () => {
157 console.log('');
158 console.log('⚠️ Interrupted by user');
159 console.log('Closing connection...');
160 ws.close(1000, 'User interrupted');
161});
162
163// Timeout after 30 seconds
164setTimeout(() => {
165 if (ws.readyState === WebSocket.OPEN) {
166 console.log('⏱️ Test timeout (30 seconds) - closing connection');
167 ws.close(1000, 'Test completed');
168 }
169}, 30000);
170
171console.log('Test running... (press Ctrl+C to stop)');
172console.log('');