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{}} }