11package host
22
33import (
4- "context"
54 "os"
65 "path/filepath"
76 "sort"
@@ -16,19 +15,6 @@ import (
1615 "gopkg.in/yaml.v2"
1716)
1817
19- const (
20- OpAdd Op = "add"
21- OpRemove Op = "remove"
22- OpPatch Op = "patch"
23- )
24-
25- type Op string
26-
27- type HostOp struct {
28- Host * Host
29- Op Op
30- }
31-
3218type Host struct {
3319 Host string `yaml:"host"`
3420 Captcha captcha.Captcha `yaml:"captcha"`
@@ -40,10 +26,8 @@ type Host struct {
4026
4127type Manager struct {
4228 Hosts []* Host
43- Chan chan HostOp
4429 Logger * log.Entry
45- cache map [string ]* Host
46- sync.RWMutex
30+ cache sync.Map // map[string]*Host - thread-safe cache for matched hosts
4731}
4832
4933const t = `
@@ -67,61 +51,36 @@ func (h *Manager) String() string {
6751func NewManager (l * log.Entry ) * Manager {
6852 return & Manager {
6953 Hosts : make ([]* Host , 0 ),
70- Chan : make (chan HostOp ),
7154 Logger : l ,
72- cache : make ( map [ string ] * Host ),
55+ // cache is a sync.Map, zero value is ready to use
7356 }
7457}
7558
7659func (h * Manager ) MatchFirstHost (toMatch string ) * Host {
77- h .RLock ()
78- defer h .RUnlock ()
60+ // Check cache first (thread-safe via sync.Map)
61+ if cached , ok := h .cache .Load (toMatch ); ok {
62+ if host , ok := cached .(* Host ); ok {
63+ host .logger .WithField ("requested_host" , toMatch ).Debug ("matched host from cache" )
64+ return host
65+ }
66+ }
7967
8068 if len (h .Hosts ) == 0 {
8169 return nil
8270 }
8371
84- if host , ok := h .cache [toMatch ]; ok {
85- host .logger .WithField ("requested_host" , toMatch ).Debug ("matched host from cache" )
86- return host
87- }
88-
8972 for _ , host := range h .Hosts {
9073 matched , err := filepath .Match (host .Host , toMatch )
9174 if matched && err == nil {
9275 host .logger .WithField ("requested_host" , toMatch ).Debug ("matched host pattern" )
93- h .cache [ toMatch ] = host
76+ h .cache . Store ( toMatch , host ) // Thread-safe via sync.Map
9477 return host
9578 }
9679 }
9780 h .Logger .WithField ("requested_host" , toMatch ).Debug ("no matching host found" )
9881 return nil
9982}
10083
101- func (h * Manager ) Run (ctx context.Context ) {
102-
103- for {
104- select {
105- case instruction := <- h .Chan :
106- h .Lock ()
107- switch instruction .Op {
108- case OpRemove :
109- h .cache = make (map [string ]* Host )
110- h .removeHost (instruction .Host )
111- case OpAdd :
112- h .cache = make (map [string ]* Host )
113- h .addHost (instruction .Host )
114- h .sort ()
115- case OpPatch :
116- h .patchHost (instruction .Host )
117- }
118- h .Unlock ()
119- case <- ctx .Done ():
120- return
121- }
122- }
123- }
124-
12584func (h * Manager ) LoadFromDirectory (path string ) error {
12685 files , err := filepath .Glob (filepath .Join (path , "*.yaml" ))
12786 if err != nil {
@@ -132,10 +91,7 @@ func (h *Manager) LoadFromDirectory(path string) error {
13291 if err != nil {
13392 return err
13493 }
135- h .Chan <- HostOp {
136- Host : host ,
137- Op : OpAdd ,
138- }
94+ h .AddHost (host )
13995 }
14096 return nil
14197}
@@ -177,24 +133,6 @@ func (h *Manager) sort() {
177133 })
178134}
179135
180- func (h * Manager ) removeHost (host * Host ) {
181- for i , th := range h .Hosts {
182- if th == host {
183- // Sessions persist in global manager, no cleanup needed
184- if i == len (h .Hosts )- 1 {
185- h .Hosts = h .Hosts [:i ]
186- } else {
187- h .Hosts = append (h .Hosts [:i ], h .Hosts [i + 1 :]... )
188- }
189- return
190- }
191- }
192- }
193-
194- func (h * Manager ) patchHost (host * Host ) {
195- //TODO
196- }
197-
198136// createHostLogger creates a logger for a host that inherits from the base logger
199137// while allowing host-specific overrides like log level
200138func (h * Manager ) createHostLogger (host * Host ) * log.Entry {
@@ -229,7 +167,9 @@ func (h *Manager) createHostLogger(host *Host) *log.Entry {
229167 return hostLogger .WithField ("host" , host .Host )
230168}
231169
232- func (h * Manager ) addHost (host * Host ) {
170+ // AddHost adds a host to the manager.
171+ // This should only be called during initialization before concurrent access begins.
172+ func (h * Manager ) AddHost (host * Host ) {
233173 // Create a logger for this host that inherits base logger values
234174 host .logger = h .createHostLogger (host )
235175
@@ -239,7 +179,7 @@ func (h *Manager) addHost(host *Host) {
239179 "has_ban" : true , // Ban is always available
240180 })
241181
242- // Initialize captcha (no longer needs sessions - SPOA handles that)
182+ // Initialize captcha
243183 if err := host .Captcha .Init (host .logger ); err != nil {
244184 host .logger .Error (err )
245185 }
@@ -249,5 +189,10 @@ func (h *Manager) addHost(host *Host) {
249189 if err := host .AppSec .Init (host .logger ); err != nil {
250190 host .logger .Error (err )
251191 }
192+
193+ // Add to Hosts slice
252194 h .Hosts = append (h .Hosts , host )
195+
196+ // Sort hosts for priority matching
197+ h .sort ()
253198}
0 commit comments