Moonshark/core/routers/staticrouter.go
2025-03-05 19:32:23 -06:00

89 lines
1.9 KiB
Go

package routers
import (
"errors"
"os"
"path/filepath"
"strings"
"sync"
)
// StaticRouter is a filesystem-based router for static files
type StaticRouter struct {
rootDir string // Root directory containing files
routes map[string]string // Direct mapping from URL path to file path
mu sync.RWMutex // Lock for concurrent access to routes
}
// NewStaticRouter creates a new StaticRouter instance
func NewStaticRouter(rootDir string) (*StaticRouter, error) {
// Verify root directory exists
info, err := os.Stat(rootDir)
if err != nil {
return nil, err
}
if !info.IsDir() {
return nil, errors.New("root path is not a directory")
}
r := &StaticRouter{
rootDir: rootDir,
routes: make(map[string]string),
}
// Build routes
if err := r.buildRoutes(); err != nil {
return nil, err
}
return r, nil
}
// buildRoutes scans the root directory and builds the routing map
func (r *StaticRouter) buildRoutes() error {
return filepath.Walk(r.rootDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// Skip directories
if info.IsDir() {
return nil
}
// Get relative path for URL
relPath, err := filepath.Rel(r.rootDir, path)
if err != nil {
return err
}
// Convert to URL path with forward slashes for consistency
urlPath := "/" + strings.ReplaceAll(relPath, "\\", "/")
// Add to routes map
r.routes[urlPath] = path
return nil
})
}
// Match finds a file path for the given URL path
func (r *StaticRouter) Match(path string) (string, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
filePath, found := r.routes[path]
return filePath, found
}
// Refresh rebuilds the router by rescanning the root directory
func (r *StaticRouter) Refresh() error {
r.mu.Lock()
defer r.mu.Unlock()
// Clear routes
r.routes = make(map[string]string)
// Rebuild routes
return r.buildRoutes()
}