package handler import ( "errors" "io/fs" "net/http" "os" "path/filepath" "strings" "git.pyer.club/kingecg/gologger" ) type FileHandler struct { Root string Default string http.FileSystem } func (f FileHandler) Open(name string) (http.File, error) { l := gologger.GetLogger("filehandler") if strings.HasPrefix(name, "../") { return nil, errors.New("not permitted") } rPath := filepath.Join(f.Root, strings.TrimPrefix(name, "/")) l.Debug("access:", rPath) // if rPath == f.Root { // if f.Default == "" { // return nil, errors.New("not permit list dir") // } // rPath = filepath.Join(rPath, f.Default) // } fInfo, _, err := FileExists(rPath) if err != nil { l.Error("access file error:", rPath, err) return nil, err } if fInfo.IsDir() && rPath != strings.TrimSuffix(f.Root, "/") { return nil, errors.New("not permit list dir") } if fInfo.Mode() == fs.ModeSymlink { return nil, errors.New("not permit follow symbol link") } fp, err := os.Open(rPath) if err != nil { l.Error("open file fail", err) return nil, err } return fp, nil } func FileExists(name string) (os.FileInfo, bool, error) { info, err := os.Stat(name) if err != nil { return nil, os.IsExist(err), err } return info, true, nil } func NewFileHandler(f FileHandler) http.Handler { return http.FileServer(f) }