modweb/utils/joinedfs.go

98 lines
1.8 KiB
Go

package utils
import (
"fmt"
"net/http"
"os"
"strings"
)
type JoinedFilesystem struct {
DefaultSystem http.FileSystem
Systems map[string]http.FileSystem
}
func Stat(fs http.FileSystem, filename string) (os.FileInfo, error) {
file, err := fs.Open(filename)
if err != nil {
return nil, err
}
return file.Stat()
}
func Readdir(fs http.FileSystem, filename string) ([]os.FileInfo, error) {
file, err := fs.Open(filename)
if err != nil {
return nil, err
}
return file.Readdir(-1)
}
func (s *JoinedFilesystem) GetRoot() (http.File, error) {
root, err := s.DefaultSystem.Open("/")
if err != nil {
return nil, err
}
rootStat, err := root.Stat()
if err != nil {
return nil, err
}
rootContent, err := root.Readdir(-1)
if err != nil {
return nil, err
}
for prefix, fs := range s.Systems {
fsRoot, err := fs.Open("/")
if err != nil {
fmt.Println(err)
continue
}
fsRootStat, err := fsRoot.Stat()
if err != nil {
fmt.Println(err)
continue
}
rootContent = append(rootContent, ChangeFileInfoName(fsRootStat, prefix))
}
return FakeDir{Self: rootStat, Content: rootContent}, nil
}
func (s *JoinedFilesystem) Open(filename string) (http.File, error) {
if filename == "/" {
return s.GetRoot()
}
parts := strings.Split(filename, "/")
var newFilename string
if len(parts) == 2 {
newFilename = "/"
} else {
newFilename = strings.Join(parts[2:], "/")
}
for prefix, fs := range s.Systems {
if parts[1] == prefix {
file, err := fs.Open(newFilename)
if err == nil {
return file, nil
}
}
}
return s.DefaultSystem.Open(filename)
}
func (s *JoinedFilesystem) Register(prefix string, system http.FileSystem) {
s.Systems[prefix] = system
}
func JoinedFS(def http.FileSystem) *JoinedFilesystem {
return &JoinedFilesystem{DefaultSystem: def, Systems: map[string]http.FileSystem{}}
}