chore: refactor codes

Kim committed Oct 21, 2025 at 20:16 UTC a2bc749eeeb75c89537194414dfa48ff22e609ba
5 files changed +62 -52
cmd/server/view.go
+18 -24
@@ -27,7 +27,7 @@ func serveHTTP(ctx context.Context, addr string, d *relaydns.RelayServer, h host
27 http.NotFound(w, r)
28 return
29 }
30 - rows := make([]row, 0)
30 + rows := make([]relaydns.AdminRow, 0)
31 for _, v := range d.Hosts() {
32 ttl := ""
33 if v.Info.TTL > 0 {
@@ -41,7 +41,7 @@ func serveHTTP(ctx context.Context, addr string, d *relaydns.RelayServer, h host
41 } else if strings.Contains(p, "http") {
42 kind = "HTTP"
43 }
44 - rows = append(rows, row{
44 + rows = append(rows, relaydns.AdminRow{
45 Peer: v.Info.Peer,
46 Name: v.Info.Name,
47 DNS: v.Info.DNS,
@@ -54,7 +54,7 @@ func serveHTTP(ctx context.Context, addr string, d *relaydns.RelayServer, h host
54 }
55 w.Header().Set("Content-Type", "text/html; charset=utf-8")
56 log.Debug().Int("clients", len(rows)).Msg("render admin index")
57 - _ = adminIndexTmpl.Execute(w, page{
57 + _ = adminIndexTmpl.Execute(w, relaydns.AdminPage{
58 NodeID: h.ID().String(),
59 Addrs: relaydns.BuildAddrs(h),
60 Rows: rows,
@@ -77,12 +77,24 @@ func serveHTTP(ctx context.Context, addr string, d *relaydns.RelayServer, h host
77 d.ProxyHTTP(w, r, peerID, pathSuffix)
78 })
79
80 - // JSON hosts
80 + // JSON hosts (namespaced snapshot with server peer and connected peers only)
81 mux.HandleFunc("/hosts", func(w http.ResponseWriter, r *http.Request) {
82 - _ = json.NewEncoder(w).Encode(d.Hosts())
82 + list := d.Hosts()
83 + peers := make([]string, 0, len(list))
84 + for _, v := range list {
85 + if v.Connected {
86 + peers = append(peers, v.Info.Peer)
87 + }
88 + }
89 + snap := relaydns.Hosts{
90 + ServerPeer: h.ID().String(),
91 + ServerAddrs: relaydns.BuildAddrs(h),
92 + Peers: peers,
93 + }
94 + w.Header().Set("Content-Type", "application/json")
95 + _ = json.NewEncoder(w).Encode(snap)
96 })
97
85 - // Health
98 mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
99 type info struct {
100 Status string `json:"status"`
@@ -100,24 +112,6 @@ func serveHTTP(ctx context.Context, addr string, d *relaydns.RelayServer, h host
112 }
113 }
114
103 -// view model types used by template rendering
104 -type row struct {
105 - Peer string
106 - Name string
107 - DNS string
108 - LastSeen string
109 - Link string
110 - TTL string
111 - Connected bool
112 - Kind string
113 -}
114 -
115 -type page struct {
116 - NodeID string
117 - Addrs []string
118 - Rows []row
119 -}
120 -
115 var adminIndexTmpl = template.Must(template.New("admin-index").Parse(`<!doctype html>
116 <html lang="ko">
117 <head>
relaydns/client.go
+6 -6
@@ -180,16 +180,16 @@ func (b *RelayClient) resolveBootstraps() []string {
180 boot = append(boot, b.cfg.Bootstraps...)
181 }
182 if b.cfg.ServerURL != "" {
183 - if addrs, err := fetchMultiaddrsFromHealth(b.cfg.ServerURL, b.cfg.HTTPTimeout); err != nil {
183 + if addrs, err := fetchMultiaddrsFromHosts(b.cfg.ServerURL, b.cfg.HTTPTimeout); err != nil {
184 b.setServerHealthy(false)
185 - log.Warn().Err(err).Msgf("relaydns: fetch /health from %s failed", b.cfg.ServerURL)
185 + log.Warn().Err(err).Msgf("relaydns: fetch /hosts from %s failed", b.cfg.ServerURL)
186 } else {
187 b.setServerHealthy(true)
188 sortMultiaddrs(addrs, b.cfg.PreferQUIC, b.cfg.PreferLocal)
189 boot = append(boot, addrs...)
190 }
191 }
192 - return uniq(boot)
192 + return RemoveDuplicate(boot)
193 }
194
195 // setupStreamHandler installs the appropriate libp2p stream handler.
@@ -273,15 +273,15 @@ func (b *RelayClient) startRefreshLoop(ctx context.Context) {
273 case <-ctx.Done():
274 return
275 case <-t.C:
276 - addrs, err := fetchMultiaddrsFromHealth(b.cfg.ServerURL, b.cfg.HTTPTimeout)
276 + addrs, err := fetchMultiaddrsFromHosts(b.cfg.ServerURL, b.cfg.HTTPTimeout)
277 if err != nil {
278 b.setServerHealthy(false)
279 - log.Warn().Err(err).Msgf("refresh /health from %s failed", b.cfg.ServerURL)
279 + log.Warn().Err(err).Msgf("refresh /hosts from %s failed", b.cfg.ServerURL)
280 continue
281 }
282 b.setServerHealthy(true)
283 sortMultiaddrs(addrs, b.cfg.PreferQUIC, b.cfg.PreferLocal)
284 - addrs = uniq(addrs)
284 + addrs = RemoveDuplicate(addrs)
285 if len(addrs) > 0 {
286 // Always attempt (re)connect; ConnectBootstraps handles dedupe and quiet logging
287 ConnectBootstraps(ctx, b.h, addrs)
relaydns/server.go
+3 -5
@@ -103,10 +103,8 @@ func (s *RelayServer) collect() {
103 snap = append(snap, v)
104 }
105 s.storeMu.Unlock()
106 - if existed {
107 - log.Debug().Str("peer", ad.Peer).Str("name", ad.Name).Msg("server: updated client advert")
108 - } else {
109 - log.Info().Str("peer", ad.Peer).Str("name", ad.Name).Msg("server: added client")
106 + if !existed {
107 + log.Info().Str("peer", ad.Peer).Str("name", ad.Name).Msg("server: add new client")
108 }
109 _ = snap // snapshot kept local; selection handled explicitly via /peer
110 }
@@ -153,7 +151,7 @@ func (s *RelayServer) gc() {
151 }
152 s.storeMu.Unlock()
153 for _, r := range removed {
156 - log.Info().Str("peer", r.Info.Peer).Str("name", r.Info.Name).Dur("idle", now.Sub(r.LastSeen)).Msg("director: removed stale client")
154 + log.Info().Str("peer", r.Info.Peer).Str("name", r.Info.Name).Dur("idle", now.Sub(r.LastSeen)).Msg("server: removed stale client")
155 }
156 _ = snap
157 }
relaydns/types.go
+26
@@ -12,6 +12,12 @@ const (
12 DefaultTopic = "relaydns.backends"
13 )
14
15 +type Hosts struct {
16 + ServerPeer string `json:"serverPeer"`
17 + ServerAddrs []string `json:"serverAddrs"`
18 + Peers []string `json:"peers"` // connected peer IDs
19 +}
20 +
21 type Advertise struct {
22 Peer string `json:"peer"`
23 Name string `json:"name,omitempty"`
@@ -30,3 +36,23 @@ type HostEntry struct {
36 LastSeen time.Time
37 Connected bool
38 }
39 +
40 +// AdminPage is a simple view model used by the server admin UI template.
41 +// It intentionally lives here so other binaries can share the same model if needed.
42 +type AdminPage struct {
43 + NodeID string
44 + Addrs []string
45 + Rows []AdminRow
46 +}
47 +
48 +// AdminRow represents a single backend entry as shown on the admin index.
49 +type AdminRow struct {
50 + Peer string
51 + Name string
52 + DNS string
53 + LastSeen string
54 + Link string
55 + TTL string
56 + Connected bool
57 + Kind string
58 +}
relaydns/utils.go
+9 -17
@@ -2,7 +2,6 @@ package relaydns
2
3 import (
4 "encoding/json"
5 - "errors"
5 "fmt"
6 "net/http"
7 "net/url"
@@ -42,7 +41,7 @@ func sortMultiaddrs(addrs []string, preferQUIC, preferLocal bool) {
41 sort.SliceStable(addrs, func(i, j int) bool { return score(addrs[i]) > score(addrs[j]) })
42 }
43
45 -func uniq(ss []string) []string {
44 +func RemoveDuplicate(ss []string) []string {
45 seen := map[string]struct{}{}
46 out := make([]string, 0, len(ss))
47 for _, s := range ss {
@@ -55,17 +54,17 @@ func uniq(ss []string) []string {
54 return out
55 }
56
58 -func fetchMultiaddrsFromHealth(base string, timeout time.Duration) ([]string, error) {
57 +func fetchMultiaddrsFromHosts(base string, timeout time.Duration) ([]string, error) {
58 u, err := url.Parse(base)
59 if err != nil {
60 return nil, fmt.Errorf("parse server-url: %w", err)
61 }
63 - // ensure path ends with /health
64 - if !strings.HasSuffix(u.Path, "/health") {
62 + // ensure path ends with /hosts
63 + if !strings.HasSuffix(u.Path, "/hosts") {
64 if u.Path == "" || u.Path == "/" {
66 - u.Path = "/health"
65 + u.Path = "/hosts"
66 } else {
68 - u.Path = strings.TrimSuffix(u.Path, "/") + "/health"
67 + u.Path = strings.TrimSuffix(u.Path, "/") + "/hosts"
68 }
69 }
70 client := &http.Client{Timeout: timeout}
@@ -76,19 +75,12 @@ func fetchMultiaddrsFromHealth(base string, timeout time.Duration) ([]string, er
75 }
76 defer resp.Body.Close()
77
79 - var payload struct {
80 - Status string `json:"status"`
81 - PeerID string `json:"peerId"`
82 - Multiaddrs []string `json:"multiaddrs"`
83 - }
78 + var payload Hosts
79 if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
80 return nil, err
81 }
87 - if payload.Status != "ok" {
88 - return nil, errors.New("health not ok")
89 - }
90 - addrs := make([]string, 0, len(payload.Multiaddrs))
91 - for _, s := range payload.Multiaddrs {
82 + addrs := make([]string, 0, len(payload.ServerAddrs))
83 + for _, s := range payload.ServerAddrs {
84 // sanity check
85 if strings.Contains(s, "/p2p/") && (strings.Contains(s, "/ip4/") || strings.Contains(s, "/ip6/")) {
86 addrs = append(addrs, s)