From 73ae4d05c13cc6b4d34140a87d555ad7efbf37e8 Mon Sep 17 00:00:00 2001 From: johnlin Date: Thu, 12 Mar 2026 22:49:37 +0800 Subject: [PATCH] fix(probe): use protocol-aware default port for endpoint probing --- src/probe.ts | 16 +++++++++++----- tests/probe.test.ts | 24 +++++++++++++++++++++++- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/probe.ts b/src/probe.ts index 4c8ef91..f7e66e5 100644 --- a/src/probe.ts +++ b/src/probe.ts @@ -7,16 +7,22 @@ export type ProbeResult = { ok: boolean; ms: number; error?: string } * Opens a TCP connection to the host and port parsed from `endpoint` to verify * reachability before the OTel SDK initialises. Resolves within 5 seconds. */ -export function probeEndpoint(endpoint: string): Promise { - let host: string - let port: number +export function parseEndpoint(endpoint: string): { host: string; port: number } | null { try { const url = new URL(endpoint) - host = url.hostname - port = parseInt(url.port || "4317", 10) + const defaultPort = url.protocol === "http:" ? 80 : url.protocol === "https:" ? 443 : 4317 + return { host: url.hostname, port: url.port ? parseInt(url.port, 10) : defaultPort } } catch { + return null + } +} + +export function probeEndpoint(endpoint: string): Promise { + const parsed = parseEndpoint(endpoint) + if (!parsed) { return Promise.resolve({ ok: false, ms: 0, error: `invalid endpoint URL: ${endpoint}` }) } + const { host, port } = parsed return new Promise((resolve) => { const start = Date.now() const socket = net.createConnection({ host, port }, () => { diff --git a/tests/probe.test.ts b/tests/probe.test.ts index 9e3dd6e..7c57b97 100644 --- a/tests/probe.test.ts +++ b/tests/probe.test.ts @@ -1,5 +1,27 @@ import { describe, test, expect } from "bun:test" -import { probeEndpoint } from "../src/probe.ts" +import { probeEndpoint, parseEndpoint } from "../src/probe.ts" + +describe("parseEndpoint", () => { + test("uses port 80 for http:// URLs without explicit port", () => { + expect(parseEndpoint("http://api.honeycomb.io")).toEqual({ host: "api.honeycomb.io", port: 80 }) + }) + + test("uses port 443 for https:// URLs without explicit port", () => { + expect(parseEndpoint("https://api.honeycomb.io")).toEqual({ host: "api.honeycomb.io", port: 443 }) + }) + + test("uses explicit port when provided", () => { + expect(parseEndpoint("http://localhost:4317")).toEqual({ host: "localhost", port: 4317 }) + }) + + test("defaults to 4317 for unknown protocols without explicit port", () => { + expect(parseEndpoint("grpc://api.honeycomb.io")).toEqual({ host: "api.honeycomb.io", port: 4317 }) + }) + + test("returns null for invalid URLs", () => { + expect(parseEndpoint("not a url")).toBeNull() + }) +}) describe("probeEndpoint", () => { test("returns error for malformed URL (no scheme)", async () => {