Salīdzināt revīzijas
1 Revīzijas
main
...
fix/67-rea
| Autors | SHA1 | Datums | |
|---|---|---|---|
| 83643f84ab |
60
internal/handlers/domains.go
Parasts fails
60
internal/handlers/domains.go
Parasts fails
@@ -0,0 +1,60 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// domainResponse represents a single domain in the API response.
|
||||
type domainResponse struct {
|
||||
Domain string `json:"domain"`
|
||||
Nameservers []string `json:"nameservers,omitempty"`
|
||||
LastChecked string `json:"lastChecked,omitempty"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// domainsResponse is the top-level response for GET /api/v1/domains.
|
||||
type domainsResponse struct {
|
||||
Domains []domainResponse `json:"domains"`
|
||||
}
|
||||
|
||||
// HandleDomains returns the configured domains and their status.
|
||||
func (h *Handlers) HandleDomains() http.HandlerFunc {
|
||||
return func(
|
||||
writer http.ResponseWriter,
|
||||
request *http.Request,
|
||||
) {
|
||||
configured := h.config.Domains
|
||||
snapshot := h.state.GetSnapshot()
|
||||
|
||||
domains := make(
|
||||
[]domainResponse, 0, len(configured),
|
||||
)
|
||||
|
||||
for _, domain := range configured {
|
||||
dr := domainResponse{
|
||||
Domain: domain,
|
||||
Status: "pending",
|
||||
}
|
||||
|
||||
ds, ok := snapshot.Domains[domain]
|
||||
if ok {
|
||||
dr.Nameservers = ds.Nameservers
|
||||
dr.Status = "ok"
|
||||
|
||||
if !ds.LastChecked.IsZero() {
|
||||
dr.LastChecked = ds.LastChecked.
|
||||
Format(time.RFC3339)
|
||||
}
|
||||
}
|
||||
|
||||
domains = append(domains, dr)
|
||||
}
|
||||
|
||||
h.respondJSON(
|
||||
writer, request,
|
||||
&domainsResponse{Domains: domains},
|
||||
http.StatusOK,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,11 @@ import (
|
||||
|
||||
"go.uber.org/fx"
|
||||
|
||||
"sneak.berlin/go/dnswatcher/internal/config"
|
||||
"sneak.berlin/go/dnswatcher/internal/globals"
|
||||
"sneak.berlin/go/dnswatcher/internal/healthcheck"
|
||||
"sneak.berlin/go/dnswatcher/internal/logger"
|
||||
"sneak.berlin/go/dnswatcher/internal/state"
|
||||
)
|
||||
|
||||
// Params contains dependencies for Handlers.
|
||||
@@ -20,6 +22,8 @@ type Params struct {
|
||||
Logger *logger.Logger
|
||||
Globals *globals.Globals
|
||||
Healthcheck *healthcheck.Healthcheck
|
||||
State *state.State
|
||||
Config *config.Config
|
||||
}
|
||||
|
||||
// Handlers provides HTTP request handlers.
|
||||
@@ -28,6 +32,8 @@ type Handlers struct {
|
||||
params *Params
|
||||
globals *globals.Globals
|
||||
hc *healthcheck.Healthcheck
|
||||
state *state.State
|
||||
config *config.Config
|
||||
}
|
||||
|
||||
// New creates a new Handlers instance.
|
||||
@@ -37,6 +43,8 @@ func New(_ fx.Lifecycle, params Params) (*Handlers, error) {
|
||||
params: ¶ms,
|
||||
globals: params.Globals,
|
||||
hc: params.Healthcheck,
|
||||
state: params.State,
|
||||
config: params.Config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -44,7 +52,7 @@ func (h *Handlers) respondJSON(
|
||||
writer http.ResponseWriter,
|
||||
_ *http.Request,
|
||||
data any,
|
||||
status int,
|
||||
status int, //nolint:unparam // general-purpose utility; status varies in future use
|
||||
) {
|
||||
writer.Header().Set("Content-Type", "application/json")
|
||||
writer.WriteHeader(status)
|
||||
|
||||
120
internal/handlers/hostnames.go
Parasts fails
120
internal/handlers/hostnames.go
Parasts fails
@@ -0,0 +1,120 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"sneak.berlin/go/dnswatcher/internal/state"
|
||||
)
|
||||
|
||||
// nameserverRecordResponse represents one nameserver's records
|
||||
// in the API response.
|
||||
type nameserverRecordResponse struct {
|
||||
Nameserver string `json:"nameserver"`
|
||||
Records map[string][]string `json:"records"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error,omitempty"`
|
||||
LastChecked string `json:"lastChecked,omitempty"`
|
||||
}
|
||||
|
||||
// hostnameResponse represents a single hostname in the API response.
|
||||
type hostnameResponse struct {
|
||||
Hostname string `json:"hostname"`
|
||||
Nameservers []nameserverRecordResponse `json:"nameservers,omitempty"`
|
||||
LastChecked string `json:"lastChecked,omitempty"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// hostnamesResponse is the top-level response for
|
||||
// GET /api/v1/hostnames.
|
||||
type hostnamesResponse struct {
|
||||
Hostnames []hostnameResponse `json:"hostnames"`
|
||||
}
|
||||
|
||||
// HandleHostnames returns the configured hostnames and their status.
|
||||
func (h *Handlers) HandleHostnames() http.HandlerFunc {
|
||||
return func(
|
||||
writer http.ResponseWriter,
|
||||
request *http.Request,
|
||||
) {
|
||||
configured := h.config.Hostnames
|
||||
snapshot := h.state.GetSnapshot()
|
||||
|
||||
hostnames := make(
|
||||
[]hostnameResponse, 0, len(configured),
|
||||
)
|
||||
|
||||
for _, hostname := range configured {
|
||||
hr := hostnameResponse{
|
||||
Hostname: hostname,
|
||||
Status: "pending",
|
||||
}
|
||||
|
||||
hs, ok := snapshot.Hostnames[hostname]
|
||||
if ok {
|
||||
hr.Status = "ok"
|
||||
|
||||
if !hs.LastChecked.IsZero() {
|
||||
hr.LastChecked = hs.LastChecked.
|
||||
Format(time.RFC3339)
|
||||
}
|
||||
|
||||
hr.Nameservers = buildNameserverRecords(
|
||||
hs,
|
||||
)
|
||||
}
|
||||
|
||||
hostnames = append(hostnames, hr)
|
||||
}
|
||||
|
||||
h.respondJSON(
|
||||
writer, request,
|
||||
&hostnamesResponse{Hostnames: hostnames},
|
||||
http.StatusOK,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// buildNameserverRecords converts the per-nameserver state map
|
||||
// into a sorted slice for deterministic JSON output.
|
||||
func buildNameserverRecords(
|
||||
hs *state.HostnameState,
|
||||
) []nameserverRecordResponse {
|
||||
if hs.RecordsByNameserver == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
nsNames := make(
|
||||
[]string, 0, len(hs.RecordsByNameserver),
|
||||
)
|
||||
for ns := range hs.RecordsByNameserver {
|
||||
nsNames = append(nsNames, ns)
|
||||
}
|
||||
|
||||
sort.Strings(nsNames)
|
||||
|
||||
records := make(
|
||||
[]nameserverRecordResponse, 0, len(nsNames),
|
||||
)
|
||||
|
||||
for _, ns := range nsNames {
|
||||
nsr := hs.RecordsByNameserver[ns]
|
||||
|
||||
entry := nameserverRecordResponse{
|
||||
Nameserver: ns,
|
||||
Records: nsr.Records,
|
||||
Status: nsr.Status,
|
||||
Error: nsr.Error,
|
||||
}
|
||||
|
||||
if !nsr.LastChecked.IsZero() {
|
||||
entry.LastChecked = nsr.LastChecked.
|
||||
Format(time.RFC3339)
|
||||
}
|
||||
|
||||
records = append(records, entry)
|
||||
}
|
||||
|
||||
return records
|
||||
}
|
||||
@@ -28,6 +28,8 @@ func (s *Server) SetupRoutes() {
|
||||
// API v1 routes
|
||||
s.router.Route("/api/v1", func(r chi.Router) {
|
||||
r.Get("/status", s.handlers.HandleStatus())
|
||||
r.Get("/domains", s.handlers.HandleDomains())
|
||||
r.Get("/hostnames", s.handlers.HandleHostnames())
|
||||
})
|
||||
|
||||
// Metrics endpoint (optional, with basic auth)
|
||||
|
||||
Atsaukties uz šo jaunā problēmā
Block a user