go-dns/http_server.go

103 lines
2.3 KiB
Go
Raw Permalink Normal View History

2026-04-03 20:32:04 +00:00
package dns
import (
"context"
"encoding/json"
"net"
"net/http"
"strconv"
"time"
)
2026-04-03 22:50:20 +00:00
// HealthServer wraps the `/health` listener returned by ServeHTTPHealth.
2026-04-03 21:28:04 +00:00
//
// server, err := service.ServeHTTPHealth("127.0.0.1", 5554)
// defer func() { _ = server.Close() }()
2026-04-03 21:43:52 +00:00
// fmt.Println("health at", server.Address())
2026-04-03 22:28:41 +00:00
type HealthServer struct {
2026-04-03 20:32:04 +00:00
listener net.Listener
server *http.Server
}
2026-04-03 22:28:41 +00:00
// HTTPServer is kept as a compatibility alias for HealthServer.
type HTTPServer = HealthServer
2026-04-03 22:31:29 +00:00
func (server *HealthServer) HealthAddress() string {
2026-04-03 20:32:04 +00:00
if server == nil || server.listener == nil {
return ""
}
return server.listener.Addr().String()
}
2026-04-03 22:31:29 +00:00
// Address is retained for compatibility with older call sites.
func (server *HealthServer) Address() string {
return server.HealthAddress()
}
2026-04-03 22:28:41 +00:00
func (server *HealthServer) Close() error {
2026-04-03 20:32:04 +00:00
if server == nil {
return nil
}
shutdownContext, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
if server.server != nil {
if err := server.server.Shutdown(shutdownContext); err != nil {
_ = server.server.Close()
return err
}
return nil
}
if server.listener != nil {
return server.listener.Close()
}
return nil
}
// ServeHTTPHealth starts the health endpoint.
2026-04-03 20:32:04 +00:00
//
// server, err := service.ServeHTTPHealth("127.0.0.1", 5554)
// defer func() { _ = server.Close() }()
2026-04-03 22:31:29 +00:00
// resp, _ := http.Get("http://" + server.HealthAddress() + "/health")
2026-04-03 22:28:41 +00:00
func (service *Service) ServeHTTPHealth(bind string, port int) (*HealthServer, error) {
2026-04-03 20:32:04 +00:00
if bind == "" {
bind = "127.0.0.1"
}
if port <= 0 {
port = service.resolveHTTPPort()
}
2026-04-03 20:32:04 +00:00
address := net.JoinHostPort(bind, strconv.Itoa(port))
listener, err := net.Listen("tcp", address)
if err != nil {
return nil, err
}
mux := http.NewServeMux()
mux.HandleFunc("/health", func(responseWriter http.ResponseWriter, request *http.Request) {
if request.Method != http.MethodGet {
responseWriter.WriteHeader(http.StatusMethodNotAllowed)
return
}
responseWriter.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(responseWriter).Encode(service.Health())
})
server := &http.Server{
Handler: mux,
}
2026-04-03 22:28:41 +00:00
httpServer := &HealthServer{
2026-04-03 20:32:04 +00:00
listener: listener,
server: server,
}
go func() {
_ = server.Serve(listener)
}()
return httpServer, nil
}