package server import ( "io/fs" "net/http" ) // filesOnly wraps an http.FileSystem so that directories do not exist as // far as http.FileServer is concerned. FileServer asks the filesystem for // the directory first and generates its index from what it gets back; // refusing the Open is therefore the whole control, and it leaves the // path handling, content sniffing and range support of FileServer intact. // // Enumerating what a binary ships is a capability no caller needs, and // the embedded set grows as a project seeded from this template adds to // it. type filesOnly struct { inner http.FileSystem } // Open serves a file and refuses a directory with fs.ErrNotExist, which // http.FileServer maps to 404 — the same answer a path that is not // embedded at all gets. func (f filesOnly) Open(name string) (http.File, error) { file, err := f.inner.Open(name) if err != nil { // Unwrapped on purpose: http.FileServer inspects this error, // and wrapping hides fs.ErrNotExist from it. //nolint:wrapcheck // see above. return nil, err } info, err := file.Stat() if err != nil { _ = file.Close() //nolint:wrapcheck // as above. return nil, err } if info.IsDir() { _ = file.Close() return nil, fs.ErrNotExist } return file, nil }