mirror of
https://github.com/yusing/godoxy.git
synced 2026-01-11 22:30:47 +01:00
91 lines
2.2 KiB
Go
91 lines
2.2 KiB
Go
package handler
|
|
|
|
import (
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/bytedance/sonic"
|
|
healthcheck "github.com/yusing/godoxy/internal/health/check"
|
|
"github.com/yusing/godoxy/internal/types"
|
|
)
|
|
|
|
func CheckHealth(w http.ResponseWriter, r *http.Request) {
|
|
query := r.URL.Query()
|
|
scheme := query.Get("scheme")
|
|
if scheme == "" {
|
|
http.Error(w, "missing scheme", http.StatusBadRequest)
|
|
return
|
|
}
|
|
timeout := parseMsOrDefault(query.Get("timeout"))
|
|
|
|
var (
|
|
result types.HealthCheckResult
|
|
err error
|
|
)
|
|
switch scheme {
|
|
case "fileserver":
|
|
path := query.Get("path")
|
|
if path == "" {
|
|
http.Error(w, "missing path", http.StatusBadRequest)
|
|
return
|
|
}
|
|
result, err = healthcheck.FileServer(path)
|
|
case "http", "https", "h2c": // path is optional
|
|
host := query.Get("host")
|
|
path := query.Get("path")
|
|
if host == "" {
|
|
http.Error(w, "missing host", http.StatusBadRequest)
|
|
return
|
|
}
|
|
url := url.URL{Scheme: scheme, Host: host}
|
|
if scheme == "h2c" {
|
|
result, err = healthcheck.H2C(r.Context(), &url, http.MethodHead, path, timeout)
|
|
} else {
|
|
result, err = healthcheck.HTTP(&url, http.MethodHead, path, timeout)
|
|
}
|
|
case "tcp", "udp", "tcp4", "udp4", "tcp6", "udp6":
|
|
host := query.Get("host")
|
|
if host == "" {
|
|
http.Error(w, "missing host", http.StatusBadRequest)
|
|
return
|
|
}
|
|
hasPort := strings.Contains(host, ":")
|
|
port := query.Get("port")
|
|
if port != "" && hasPort {
|
|
http.Error(w, "port and host with port cannot both be provided", http.StatusBadRequest)
|
|
return
|
|
}
|
|
if port != "" {
|
|
host = net.JoinHostPort(host, port)
|
|
}
|
|
url := url.URL{Scheme: scheme, Host: host}
|
|
result, err = healthcheck.Stream(r.Context(), &url, timeout)
|
|
}
|
|
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadGateway)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusOK)
|
|
sonic.ConfigDefault.NewEncoder(w).Encode(result)
|
|
}
|
|
|
|
func parseMsOrDefault(msStr string) time.Duration {
|
|
if msStr == "" {
|
|
return types.HealthCheckTimeoutDefault
|
|
}
|
|
|
|
timeoutMs, _ := strconv.ParseInt(msStr, 10, 64)
|
|
if timeoutMs == 0 {
|
|
return types.HealthCheckTimeoutDefault
|
|
}
|
|
|
|
return time.Duration(timeoutMs) * time.Millisecond
|
|
}
|