diff --git a/core/archipelago/src/container/quadlet.rs b/core/archipelago/src/container/quadlet.rs index c0ad61c5..7c8bdd12 100644 --- a/core/archipelago/src/container/quadlet.rs +++ b/core/archipelago/src/container/quadlet.rs @@ -538,13 +538,18 @@ fn translate_health_check(hc: &archipelago_container::HealthCheck) -> Option/dev/null 2>&1; then wget -q -T {1} -O /dev/null {0}; elif command -v curl >/dev/null 2>&1; then curl -fsS -m {1} {0}; else exit 0; fi", - final_url, helper_timeout + "if command -v wget >/dev/null 2>&1; then wget -q -T {1} -O /dev/null {0}; elif command -v curl >/dev/null 2>&1; then curl -fsS -m {1} {0}; elif command -v bash >/dev/null 2>&1; then bash -c 'exec 3<>/dev/tcp/{2}/{3}'; else exit 0; fi", + final_url, helper_timeout, tcp_host, tcp_port ) } "cmd" => hc.endpoint.as_deref()?.to_string(), @@ -558,6 +563,24 @@ fn translate_health_check(hc: &archipelago_container::HealthCheck) -> Option (String, u16) { + let (default_port, rest) = if let Some(rest) = url.strip_prefix("https://") { + (443, rest) + } else { + (80, url.strip_prefix("http://").unwrap_or(url)) + }; + let authority = rest.split('/').next().unwrap_or(rest); + match authority.rsplit_once(':') { + Some((host, port)) => match port.parse::() { + Ok(port) => (host.to_string(), port), + Err(_) => (authority.to_string(), default_port), + }, + None => (authority.to_string(), default_port), + } +} + fn health_timeout_seconds(raw: &str) -> u64 { let trimmed = raw.trim(); if trimmed.is_empty() { @@ -1459,7 +1482,22 @@ app: let h = translate_health_check(&http).expect("http must translate"); assert_eq!( h.cmd, - "if command -v wget >/dev/null 2>&1; then wget -q -T 3 -O /dev/null http://localhost:8080/health; elif command -v curl >/dev/null 2>&1; then curl -fsS -m 3 http://localhost:8080/health; else exit 0; fi" + "if command -v wget >/dev/null 2>&1; then wget -q -T 3 -O /dev/null http://localhost:8080/health; elif command -v curl >/dev/null 2>&1; then curl -fsS -m 3 http://localhost:8080/health; elif command -v bash >/dev/null 2>&1; then bash -c 'exec 3<>/dev/tcp/localhost/8080'; else exit 0; fi" + ); + + // The /dev/tcp fallback must target the URL's host:port, with + // scheme-default ports when the authority carries none. + assert_eq!( + health_url_host_port("http://localhost:8080/health"), + ("localhost".to_string(), 8080) + ); + assert_eq!( + health_url_host_port("http://127.0.0.1/"), + ("127.0.0.1".to_string(), 80) + ); + assert_eq!( + health_url_host_port("https://localhost/status"), + ("localhost".to_string(), 443) ); let cmdck = HealthCheck {