From 72038d9ad1d3e6cc34dde8e23c0a0fafed913eb9 Mon Sep 17 00:00:00 2001 From: badbl0cks <4161747+badbl0cks@users.noreply.github.com> Date: Tue, 29 Jul 2025 16:49:43 -0700 Subject: [PATCH] fix: correct proxy agent configuration and enhance testing --- app/pages/proxy-test.vue | 102 ++++++++++++++++++- server/api/proxy-test.get.js | 190 +++++++++++++++++++++++------------ server/lib/http-client.js | 6 +- 3 files changed, 225 insertions(+), 73 deletions(-) diff --git a/app/pages/proxy-test.vue b/app/pages/proxy-test.vue index 37ed1a3..c8309ef 100644 --- a/app/pages/proxy-test.vue +++ b/app/pages/proxy-test.vue @@ -106,7 +106,8 @@
-

Running tests...

+

Running tests... This may take up to 60 seconds.

+

Testing proxy connectivity and SMS gateway endpoints.

@@ -377,6 +378,57 @@ + +
+
+

Test Execution Failed

+
+ + + +
+ {{ testData.errorType || 'Error' }}: {{ testData.error }} +
+
+ +
+
+
Test Type
+
{{ testData.testType || 'Unknown' }}
+
+
+
Duration
+
{{ testData.duration || 'Unknown' }}
+
+
+
Timestamp
+
{{ testData.timestamp ? new Date(testData.timestamp).toLocaleTimeString() : 'Unknown' }}
+
+
+ +
+ +
+ Technical Details +
+
+
{{ JSON.stringify(testData.details, null, 2) }}
+
+
+ +
+

Troubleshooting Tips:

+
    +
  • Check if the WireGuard proxy container is running and accessible
  • +
  • Verify network connectivity and DNS resolution
  • +
  • Ensure SMS Gateway URL is correctly configured in environment variables
  • +
  • Check if the SMS Gateway service is running and accessible
  • +
  • Verify proxy configuration: http://wireguard:8888
  • +
+
+
+
+
@@ -417,8 +469,11 @@ Raw Test Data (JSON)
+
+ Copy this data when reporting issues or debugging. +
{{ JSON.stringify(testData, null, 2) }}
@@ -480,15 +535,52 @@ const errorSummary = computed(() => { const runTests = async (testType = "all") => { loading.value = true; + const startTime = Date.now(); + try { - const response = await $fetch(`/api/proxy-test?test=${testType}`); + // Set a generous timeout (60 seconds) for comprehensive tests + const controller = new AbortController(); + const timeoutId = setTimeout(() => { + controller.abort(); + }, 60000); + + const response = await $fetch(`/api/proxy-test?test=${testType}`, { + signal: controller.signal, + timeout: 60000 + }); + + clearTimeout(timeoutId); testData.value = response; + } catch (error) { + const duration = Date.now() - startTime; console.error("Failed to run tests:", error); - testData.value = { - error: error.message, + + // Provide comprehensive error information + const errorInfo = { + error: error.message || 'Unknown error occurred', + errorType: error.name || 'Error', + duration: `${duration}ms`, timestamp: new Date().toISOString(), + testType, + details: { + code: error.code, + status: error.status || error.statusCode, + data: error.data, + stack: error.stack + } }; + + // Handle specific error types + if (error.name === 'AbortError' || error.message?.includes('aborted')) { + errorInfo.error = `Test timed out after ${duration}ms. The proxy or SMS gateway may be unreachable.`; + errorInfo.errorType = 'Timeout'; + } else if (error.name === 'FetchError' || error.message?.includes('fetch')) { + errorInfo.error = `Network error: ${error.message}. Check proxy configuration and network connectivity.`; + errorInfo.errorType = 'Network Error'; + } + + testData.value = errorInfo; } finally { loading.value = false; } diff --git a/server/api/proxy-test.get.js b/server/api/proxy-test.get.js index f2ae5a6..1a8ce33 100644 --- a/server/api/proxy-test.get.js +++ b/server/api/proxy-test.get.js @@ -1,24 +1,33 @@ -import { ProxyAgent } from "undici"; import { httpFetchClient } from "../lib/http-client.js"; - -const proxyAgent = new ProxyAgent("http://wireguard:8888"); +import { createSmsGatewayClient } from "../lib/sms-gateway"; async function testEndpoint(url, useProxy = true, options = {}) { const startTime = Date.now(); try { - const fetchOptions = { - method: options.method || "GET", - headers: options.headers || {}, - ...options, - }; + let response; if (useProxy) { - fetchOptions.agent = proxyAgent; + if (options.method === "POST") { + response = await httpFetchClient.post( + url, + options.body, + options.headers, + ); + } else { + response = await httpFetchClient.get(url, options.headers); + } + } else { + const fetchOptions = { + method: options.method || "GET", + headers: options.headers || {}, + timeout: 15000, + ...options, + }; + response = await $fetch(url, fetchOptions); } - const response = await $fetch(url, fetchOptions); const endTime = Date.now(); - + return { success: true, url, @@ -26,7 +35,7 @@ async function testEndpoint(url, useProxy = true, options = {}) { responseTime: endTime - startTime, status: response.status || 200, data: response, - error: null + error: null, }; } catch (error) { const endTime = Date.now(); @@ -35,26 +44,27 @@ async function testEndpoint(url, useProxy = true, options = {}) { url, useProxy, responseTime: endTime - startTime, - status: error.status || null, + status: error.status || error.statusCode || null, data: null, error: { message: error.message, code: error.code, - stack: error.stack - } + name: error.name, + stack: process.env.NODE_ENV === "development" ? error.stack : undefined, + }, }; } } async function testDNSResolution(hostname) { try { - const dns = await import('dns').then(m => m.promises); + const dns = await import("dns").then((m) => m.promises); const addresses = await dns.lookup(hostname); return { success: true, hostname, addresses, - error: null + error: null, }; } catch (error) { return { @@ -63,8 +73,8 @@ async function testDNSResolution(hostname) { addresses: null, error: { message: error.message, - code: error.code - } + code: error.code, + }, }; } } @@ -72,67 +82,123 @@ async function testDNSResolution(hostname) { export default defineEventHandler(async (event) => { const config = useRuntimeConfig(); const query = getQuery(event); - const testType = query.test || 'all'; - + const testType = query.test || "all"; + const results = { timestamp: new Date().toISOString(), environment: { nodeEnv: process.env.NODE_ENV, proxyUrl: "http://wireguard:8888", smsGatewayUrl: config.androidSmsGatewayUrl, - smsGatewayBypass: config.androidSmsGatewayBypass + smsGatewayBypass: config.androidSmsGatewayBypass, }, - tests: {} + tests: {}, }; // DNS Resolution Tests - if (testType === 'all' || testType === 'dns') { + if (testType === "all" || testType === "dns") { results.tests.dns = { - wireguard: await testDNSResolution('wireguard'), - google: await testDNSResolution('google.com'), - httpbin: await testDNSResolution('httpbin.org') + wireguard: await testDNSResolution("wireguard"), + google: await testDNSResolution("google.com"), + httpbin: await testDNSResolution("httpbin.org"), }; } // Basic Connectivity Tests - if (testType === 'all' || testType === 'connectivity') { + if (testType === "all" || testType === "connectivity") { results.tests.connectivity = {}; - + // Test known good endpoints const testEndpoints = [ - 'https://httpbin.org/get', - 'https://google.com', - 'https://api.github.com' + "https://httpbin.org/get", + "https://google.com", + "https://api.github.com", ]; for (const endpoint of testEndpoints) { - const endpointKey = endpoint.replace(/[^a-zA-Z0-9]/g, '_'); - results.tests.connectivity[`${endpointKey}_direct`] = await testEndpoint(endpoint, false); - results.tests.connectivity[`${endpointKey}_proxy`] = await testEndpoint(endpoint, true); + const endpointKey = endpoint.replace(/[^a-zA-Z0-9]/g, "_"); + results.tests.connectivity[`${endpointKey}_direct`] = await testEndpoint( + endpoint, + false, + ); + results.tests.connectivity[`${endpointKey}_proxy`] = await testEndpoint( + endpoint, + true, + ); } } // SMS Gateway Specific Tests - if (testType === 'all' || testType === 'sms') { + if (testType === "all" || testType === "sms") { results.tests.smsGateway = {}; - + if (config.androidSmsGatewayUrl) { - // Test basic connectivity to SMS gateway const smsUrl = config.androidSmsGatewayUrl; - results.tests.smsGateway.proxy = await testEndpoint(smsUrl, true); - - // Test SMS gateway health endpoint if available + + // Test SMS gateway health endpoint const healthUrl = `${smsUrl}/health`; - results.tests.smsGateway.health_proxy = await testEndpoint(healthUrl, true); - + results.tests.smsGateway.health_proxy = await testEndpoint( + healthUrl, + true, + ); + // Test with authentication headers if (config.androidSmsGatewayLogin && config.androidSmsGatewayPassword) { const authHeaders = { - 'Authorization': `Basic ${Buffer.from(`${config.androidSmsGatewayLogin}:${config.androidSmsGatewayPassword}`).toString('base64')}` + Authorization: `Basic ${Buffer.from(`${config.androidSmsGatewayLogin}:${config.androidSmsGatewayPassword}`).toString("base64")}`, }; - - results.tests.smsGateway.auth_direct = await testEndpoint(smsUrl, false, { headers: authHeaders }); - results.tests.smsGateway.auth_proxy = await testEndpoint(smsUrl, true, { headers: authHeaders }); + + // Test authenticated status endpoint (this simulates real SMS gateway usage) + results.tests.smsGateway.auth_status_proxy = await testEndpoint( + smsUrl + "/device", + true, + { headers: authHeaders }, + ); + + const api = createSmsGatewayClient(config); + const message = { + phoneNumbers: ["2067452154"], + message: `Testing 1 2 3...`, + }; + const startTime = Date.now(); + try { + const msg_id = (await api.send(message)).id; + await new Promise((r) => setTimeout(r, 3000)); + const state = await api.getState(msg_id); + const endTime = Date.now(); + + results.tests.smsGateway.auth_api_send_msg = { + success: true, + url: null, + useProxy: true, + responseTime: endTime - startTime, + status: state.state, + data: "msg_id: " + state.id, + error: null, + }; + } catch (error) { + const endTime = Date.now(); + results.tests.smsGateway.auth_api_send_msg = { + success: false, + url: null, + useProxy: true, + responseTime: endTime - startTime, + status: error.status || error.statusCode || null, + data: null, + error: { + message: error.message, + code: error.code, + name: error.name, + stack: + process.env.NODE_ENV === "development" + ? error.stack + : undefined, + }, + }; + } + } else { + results.tests.smsGateway.auth_error = + "SMS Gateway credentials not configured"; } } else { results.tests.smsGateway.error = "SMS Gateway URL not configured"; @@ -140,15 +206,13 @@ export default defineEventHandler(async (event) => { } // HTTP Client Library Test - if (testType === 'all' || testType === 'httpclient') { + if (testType === "all" || testType === "httpclient") { results.tests.httpClient = {}; - + try { // Test using your existing http client - const testResult = await httpFetchClient.get('https://httpbin.org/get', { - 'User-Agent': 'Portfolio-Proxy-Test/1.0' - }); - + const testResult = await httpFetchClient.get("https://httpbin.org/get"); + results.tests.httpClient.success = true; results.tests.httpClient.data = testResult; results.tests.httpClient.error = null; @@ -163,19 +227,14 @@ export default defineEventHandler(async (event) => { } } - // Proxy Agent Direct Test - if (testType === 'all' || testType === 'proxyagent') { + // Proxy Agent Direct Test (using httpFetchClient) + if (testType === "all" || testType === "proxyagent") { results.tests.proxyAgent = {}; - + try { - // Test proxy agent directly - const response = await $fetch('https://httpbin.org/ip', { - agent: proxyAgent, - headers: { - 'User-Agent': 'Portfolio-Proxy-Test/1.0' - } - }); - + // Test proxy agent using httpFetchClient (which uses ProxyAgent internally) + const response = await httpFetchClient.get("https://httpbin.org/ip"); + results.tests.proxyAgent.success = true; results.tests.proxyAgent.data = response; results.tests.proxyAgent.error = null; @@ -185,7 +244,8 @@ export default defineEventHandler(async (event) => { results.tests.proxyAgent.error = { message: error.message, code: error.code, - stack: error.stack + name: error.name, + stack: process.env.NODE_ENV === "development" ? error.stack : undefined, }; } } diff --git a/server/lib/http-client.js b/server/lib/http-client.js index 8491d1a..ad1a720 100644 --- a/server/lib/http-client.js +++ b/server/lib/http-client.js @@ -1,14 +1,14 @@ import { ProxyAgent } from "undici"; const proxyAgent = new ProxyAgent("http://wireguard:8888"); -const REQUEST_TIMEOUT = 5000; +const REQUEST_TIMEOUT = 15000; export const httpFetchClient = { get: async (url, headers) => { const response = await $fetch(url, { method: "GET", headers, - agent: proxyAgent, + dispatcher: proxyAgent, timeout: REQUEST_TIMEOUT, }); return response; @@ -18,7 +18,7 @@ export const httpFetchClient = { method: "POST", headers: { "Content-Type": "application/json", ...headers }, body: JSON.stringify(body), - agent: proxyAgent, + dispatcher: proxyAgent, timeout: REQUEST_TIMEOUT, }); return response;