89 lines
1.9 KiB
Go
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()
|
|
}
|