Source file src/net/http/example_filesystem_test.go

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

View as plain text