| // Copyright 2018 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package http_test |
| |
| import ( |
| "io/fs" |
| "log" |
| "net/http" |
| "strings" |
| ) |
| |
| // containsDotFile reports whether name contains a path element starting with a period. |
| // The name is assumed to be a delimited by forward slashes, as guaranteed |
| // by the http.FileSystem interface. |
| func containsDotFile(name string) bool { |
| parts := strings.Split(name, "/") |
| for _, part := range parts { |
| if strings.HasPrefix(part, ".") { |
| return true |
| } |
| } |
| return false |
| } |
| |
| // dotFileHidingFile is the http.File use in dotFileHidingFileSystem. |
| // It is used to wrap the Readdir method of http.File so that we can |
| // remove files and directories that start with a period from its output. |
| type dotFileHidingFile struct { |
| http.File |
| } |
| |
| // Readdir is a wrapper around the Readdir method of the embedded File |
| // that filters out all files that start with a period in their name. |
| func (f dotFileHidingFile) Readdir(n int) (fis []fs.FileInfo, err error) { |
| files, err := f.File.Readdir(n) |
| for _, file := range files { // Filters out the dot files |
| if !strings.HasPrefix(file.Name(), ".") { |
| fis = append(fis, file) |
| } |
| } |
| return |
| } |
| |
| // dotFileHidingFileSystem is an http.FileSystem that hides |
| // hidden "dot files" from being served. |
| type dotFileHidingFileSystem struct { |
| http.FileSystem |
| } |
| |
| // Open is a wrapper around the Open method of the embedded FileSystem |
| // that serves a 403 permission error when name has a file or directory |
| // with whose name starts with a period in its path. |
| func (fsys dotFileHidingFileSystem) Open(name string) (http.File, error) { |
| if containsDotFile(name) { // If dot file, return 403 response |
| return nil, fs.ErrPermission |
| } |
| |
| file, err := fsys.FileSystem.Open(name) |
| if err != nil { |
| return nil, err |
| } |
| return dotFileHidingFile{file}, err |
| } |
| |
| func ExampleFileServer_dotFileHiding() { |
| fsys := dotFileHidingFileSystem{http.Dir(".")} |
| http.Handle("/", http.FileServer(fsys)) |
| log.Fatal(http.ListenAndServe(":8080", nil)) |
| } |