pub
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/user/go-proxy/internal/config"
|
||||
"github.com/user/go-proxy/internal/proxy"
|
||||
)
|
||||
|
||||
// routeEntry stores the configuration and its pre-compiled ReverseProxy
|
||||
type routeEntry struct {
|
||||
config config.RouterRoute
|
||||
proxy *httputil.ReverseProxy
|
||||
}
|
||||
|
||||
type Router struct {
|
||||
mu sync.RWMutex
|
||||
routes []routeEntry
|
||||
}
|
||||
|
||||
func NewRouter(cfg config.HTTPConfig) *Router {
|
||||
r := &Router{}
|
||||
r.UpdateConfig(cfg)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Router) UpdateConfig(cfg config.HTTPConfig) {
|
||||
var newRoutes []routeEntry
|
||||
|
||||
for _, routeCfg := range cfg.Routers {
|
||||
// Collect backends (support both Backends array and single BackendURL)
|
||||
backends := routeCfg.Backends
|
||||
if len(backends) == 0 && routeCfg.BackendURL != "" {
|
||||
backends = []string{routeCfg.BackendURL}
|
||||
}
|
||||
|
||||
if len(backends) == 0 {
|
||||
log.Printf("Warning: Route %s has no backends configured, skipping", routeCfg.Path)
|
||||
continue
|
||||
}
|
||||
|
||||
p, err := proxy.NewLoadBalancedHTTPProxy(backends)
|
||||
if err != nil {
|
||||
log.Printf("Error creating proxy for route %s: %v", routeCfg.Path, err)
|
||||
continue
|
||||
}
|
||||
|
||||
newRoutes = append(newRoutes, routeEntry{
|
||||
config: routeCfg,
|
||||
proxy: p,
|
||||
})
|
||||
}
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
r.routes = newRoutes
|
||||
}
|
||||
|
||||
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
r.mu.RLock()
|
||||
routes := r.routes
|
||||
r.mu.RUnlock()
|
||||
|
||||
for _, route := range routes {
|
||||
cfg := route.config
|
||||
|
||||
if cfg.Host != "" && req.Host != cfg.Host {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(req.URL.Path, cfg.Path) {
|
||||
if cfg.StripPrefix {
|
||||
req.URL.Path = strings.TrimPrefix(req.URL.Path, cfg.Path)
|
||||
if req.URL.Path == "" || req.URL.Path[0] != '/' {
|
||||
req.URL.Path = "/" + req.URL.Path
|
||||
}
|
||||
}
|
||||
|
||||
// Serve using the pre-compiled proxy
|
||||
route.proxy.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
http.Error(w, "Not Found", http.StatusNotFound)
|
||||
}
|
||||
Reference in New Issue
Block a user