github.com/ooni/oohttp@v0.7.2/example_filesystem_test.go (about)

     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/fs"
     9  	"log"
    10  	"strings"
    11  
    12  	http "github.com/ooni/oohttp"
    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  	return
    45  }
    46  
    47  // dotFileHidingFileSystem is an http.FileSystem that hides
    48  // hidden "dot files" from being served.
    49  type dotFileHidingFileSystem struct {
    50  	http.FileSystem
    51  }
    52  
    53  // Open is a wrapper around the Open method of the embedded FileSystem
    54  // that serves a 403 permission error when name has a file or directory
    55  // with whose name starts with a period in its path.
    56  func (fsys dotFileHidingFileSystem) Open(name string) (http.File, error) {
    57  	if containsDotFile(name) { // If dot file, return 403 response
    58  		return nil, fs.ErrPermission
    59  	}
    60  
    61  	file, err := fsys.FileSystem.Open(name)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	return dotFileHidingFile{file}, err
    66  }
    67  
    68  func ExampleFileServer_dotFileHiding() {
    69  	fsys := dotFileHidingFileSystem{http.Dir(".")}
    70  	http.Handle("/", http.FileServer(fsys))
    71  	log.Fatal(http.ListenAndServe(":8080", nil))
    72  }