From 6f1ecd5deecf67fbbd4331a4cb8eb471adfd564e Mon Sep 17 00:00:00 2001 From: Jason Kendall Date: Thu, 16 Jan 2025 15:54:28 -0500 Subject: [PATCH] Check types (#3) * Dev (#1) * Move status to HTTP check * Check protocol * Don't continue, just false * Rename env? * Couldn't get ENV working, so change here for now * Log invalid protocols to action * Make warning clearer * Didn't support {} * Add space, opps * Add Tcp (#2) * TCP first pass * Log before return, use this logger * different error handler * Fixes as recommended by Rabbit * More rabbit fixes --- .github/workflows/health-check.yml | 2 +- log/src/checks/tcp.ts | 17 +++++++++++++---- log/src/index.ts | 28 +++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/.github/workflows/health-check.yml b/.github/workflows/health-check.yml index ab21c6f..6dd8e4c 100644 --- a/.github/workflows/health-check.yml +++ b/.github/workflows/health-check.yml @@ -54,7 +54,7 @@ jobs: GitHub->https://github.com Facebook->https://facebook.com Never SSL->http://oldsplendidfresheclipse.neverssl.com/online/ - TCPTest->tcp://facebook.com:443 + TCPTest->tcp://tcpbin:4242 GITHUB_TOKEN: ${{ github.token }} JOB_NAME: ${{ github.workflow }} ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} diff --git a/log/src/checks/tcp.ts b/log/src/checks/tcp.ts index 0967374..fc5bb42 100644 --- a/log/src/checks/tcp.ts +++ b/log/src/checks/tcp.ts @@ -1,7 +1,7 @@ import * as net from 'net'; import { ActionLogger } from "../github/types"; -function attemptConnection(host: string, port: number): Promise { +function attemptConnection(host: string, port: number, logger: ActionLogger): Promise { return new Promise((resolve) => { const socket = new net.Socket(); @@ -11,20 +11,21 @@ function attemptConnection(host: string, port: number): Promise { // Attempt to connect to the specified host and port socket.connect(port, host, () => { // If connected, destroy the socket and resolve true + socket.removeAllListeners(); // Clean up listeners socket.destroy(); resolve(true); }); // Handle errors that occur during the connection attempt socket.on('error', (err) => { - console.error('Connection error:', err.message); + logger.error(`Connection error: ${err.message}`); socket.destroy(); resolve(false); }); // Handle timeout scenario socket.on('timeout', () => { - console.error('Connection timeout'); + logger.error('Connection timeout'); socket.destroy(); resolve(false); }); @@ -39,12 +40,20 @@ export class TCPChecker { async verifyEndpoint(): Promise { const [host, portString] = this.healthEndpoint.replace('tcp://', '').split(':'); + if (!host) { + this.logger.error('Invalid host: Host cannot be empty'); + return false; + } // Convert the port part to a number const port = parseInt(portString, 10); + if (Number.isNaN(port) || port < 1 || port > 65535) { + this.logger.error(`Invalid port number: ${portString}`); + return false; + } try { - const isConnected = await attemptConnection(host, port); + const isConnected = await attemptConnection(host, port, this.logger); if (isConnected) { this.logger.info('Connection successful'); return true; diff --git a/log/src/index.ts b/log/src/index.ts index 6c4fed4..0f43cec 100644 --- a/log/src/index.ts +++ b/log/src/index.ts @@ -39,6 +39,25 @@ const repo = getRepo(context); setOutput("repo", `${repo.owner}/${repo.repo}`); +const SUPPORTED_PROTOCOLS = { + HTTP: 'http://', + HTTPS: 'https://', + TCP: 'tcp://' +} as const; + +function isValidUrl(url: string): boolean { + try { + if (url.startsWith(SUPPORTED_PROTOCOLS.TCP)) { + const [host, port] = url.replace(SUPPORTED_PROTOCOLS.TCP, '').split(':'); + return Boolean(host && port && !Number.isNaN(parseInt(port, 10))); + } + new URL(url); + return true; + } catch { + return false; + } +} + /** * Inputs must be in style of * ```log @@ -75,15 +94,18 @@ const run = async () => { // Run tests on each required source for (const [name, url] of sources) { let result: boolean; - if (url.startsWith("http://") || url.startsWith("https://")) { + if (!isValidUrl(url)) { + result = false; + warning(`Invalid URL format for check: ${name}`); + } else if (url.startsWith(SUPPORTED_PROTOCOLS.HTTP) || url.startsWith(SUPPORTED_PROTOCOLS.HTTPS)) { const statusChecker = new HTTPChecker(name, url, logger); result = await statusChecker.verifyEndpoint(); - } else if (url.startsWith("tcp://")) { + } else if (url.startsWith(SUPPORTED_PROTOCOLS.TCP)) { const statusChecker = new TCPChecker(name, url, logger); result = await statusChecker.verifyEndpoint(); } else { result = false; - warning("Unsupported protocol for check: " + name); + warning(`Unsupported protocol for check: ${name} (URL: ${url})`); } let report: ReportFile["site"][number]["status"] | undefined = siteResult.get(name);