feat(observability): phase 3 - direct proxy creation with validation
Add standalone proxy management: - Multi-step validation pipeline (DNS, TCP, HTTP) with diagnostic hints - Proxy lifecycle: create/update/delete via NPM API with SSL auto-assign - Periodic health monitoring (5min) with event log on status transitions - Unified /api/proxies/all endpoint merging standalone + managed proxies - Frontend types and API functions for downstream UI phases
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// diagnosticHint returns a user-friendly suggestion for a validation failure.
|
||||
func diagnosticHint(step string, err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch step {
|
||||
case StepDNS:
|
||||
return "Domain cannot be resolved. Check DNS settings or use an IP address."
|
||||
|
||||
case StepTCP:
|
||||
return tcpHintFromError(err)
|
||||
|
||||
case StepHTTP:
|
||||
return httpHint(err.Error())
|
||||
|
||||
default:
|
||||
return "Validation failed: " + err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
// tcpHintFromError returns a specific hint based on the TCP error type.
|
||||
func tcpHintFromError(err error) string {
|
||||
if err == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var opErr *net.OpError
|
||||
if errors.As(err, &opErr) {
|
||||
lower := strings.ToLower(opErr.Err.Error())
|
||||
switch {
|
||||
case strings.Contains(lower, "connection refused"):
|
||||
return "Port is not accepting connections. Check if the service is running and the port is correct."
|
||||
case strings.Contains(lower, "i/o timeout") || strings.Contains(lower, "timeout"):
|
||||
return "Connection timed out. Possible firewall blocking. Check network/firewall rules."
|
||||
case strings.Contains(lower, "no route to host") || strings.Contains(lower, "host is unreachable"):
|
||||
return "Host is not reachable. Verify the IP address and network connectivity."
|
||||
}
|
||||
}
|
||||
|
||||
msg := err.Error()
|
||||
lower := strings.ToLower(msg)
|
||||
switch {
|
||||
case strings.Contains(lower, "connection refused"):
|
||||
return "Port is not accepting connections. Check if the service is running and the port is correct."
|
||||
case strings.Contains(lower, "timeout"):
|
||||
return "Connection timed out. Possible firewall blocking. Check network/firewall rules."
|
||||
default:
|
||||
return fmt.Sprintf("TCP connection failed: %s", msg)
|
||||
}
|
||||
}
|
||||
|
||||
// httpHint returns a specific hint based on the HTTP probe result.
|
||||
func httpHint(msg string) string {
|
||||
lower := strings.ToLower(msg)
|
||||
|
||||
switch {
|
||||
case strings.Contains(lower, "status"):
|
||||
return msg // Already formatted by the caller with the status code.
|
||||
case strings.Contains(lower, "timeout"):
|
||||
return "HTTP health probe timed out. The service may be slow or unresponsive."
|
||||
default:
|
||||
return "HTTP health probe failed: " + msg
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user