1// Copyright 2018 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package http_test 6 7import ( 8 "io/fs" 9 "log" 10 "net/http" 11 "strings" 12) 13 14// containsDotFile reports whether name contains a path element starting with a period. 15// The name is assumed to be a delimited by forward slashes, as guaranteed 16// by the http.FileSystem interface. 17func containsDotFile(name string) bool { 18 parts := strings.Split(name, "/") 19 for _, part := range parts { 20 if strings.HasPrefix(part, ".") { 21 return true 22 } 23 } 24 return false 25} 26 27// dotFileHidingFile is the http.File use in dotFileHidingFileSystem. 28// It is used to wrap the Readdir method of http.File so that we can 29// remove files and directories that start with a period from its output. 30type dotFileHidingFile struct { 31 http.File 32} 33 34// Readdir is a wrapper around the Readdir method of the embedded File 35// that filters out all files that start with a period in their name. 36func (f dotFileHidingFile) Readdir(n int) (fis []fs.FileInfo, err error) { 37 files, err := f.File.Readdir(n) 38 for _, file := range files { // Filters out the dot files 39 if !strings.HasPrefix(file.Name(), ".") { 40 fis = append(fis, file) 41 } 42 } 43 return 44} 45 46// dotFileHidingFileSystem is an http.FileSystem that hides 47// hidden "dot files" from being served. 48type dotFileHidingFileSystem struct { 49 http.FileSystem 50} 51 52// Open is a wrapper around the Open method of the embedded FileSystem 53// that serves a 403 permission error when name has a file or directory 54// with whose name starts with a period in its path. 55func (fsys dotFileHidingFileSystem) Open(name string) (http.File, error) { 56 if containsDotFile(name) { // If dot file, return 403 response 57 return nil, fs.ErrPermission 58 } 59 60 file, err := fsys.FileSystem.Open(name) 61 if err != nil { 62 return nil, err 63 } 64 return dotFileHidingFile{file}, err 65} 66 67func ExampleFileServer_dotFileHiding() { 68 fsys := dotFileHidingFileSystem{http.Dir(".")} 69 http.Handle("/", http.FileServer(fsys)) 70 log.Fatal(http.ListenAndServe(":8080", nil)) 71} 72