From 187a41dbf730117bd52f871009466a9679d6b718 Mon Sep 17 00:00:00 2001 From: Marcus Willock Date: Fri, 3 Aug 2018 15:13:14 +0000 Subject: [PATCH] net/http: add an example of creating a custom FileSystem The existing documentation of http.Dir is clear in that, if you want to hide your files and directories that start with a period, you must create a custom FileSystem. However, there are currently no example on how to create a custom FileSystem. This commit provides an example. Fixes #20759 Change-Id: I5a350675536f81412af384d1a316fd6cd6241563 GitHub-Last-Rev: 8b0b644cd02c59fe2461908304c44d64e8be431e GitHub-Pull-Request: golang/go#26768 Reviewed-on: https://go-review.googlesource.com/127576 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/net/http/example_filesystem_test.go | 71 +++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/net/http/example_filesystem_test.go diff --git a/src/net/http/example_filesystem_test.go b/src/net/http/example_filesystem_test.go new file mode 100644 index 0000000000..e1fd42d049 --- /dev/null +++ b/src/net/http/example_filesystem_test.go @@ -0,0 +1,71 @@ +// 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 ( + "log" + "net/http" + "os" + "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 []os.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 (fs dotFileHidingFileSystem) Open(name string) (http.File, error) { + if containsDotFile(name) { // If dot file, return 403 response + return nil, os.ErrPermission + } + + file, err := fs.FileSystem.Open(name) + if err != nil { + return nil, err + } + return dotFileHidingFile{file}, err +} + +func ExampleFileServer_dotFileHiding() { + fs := dotFileHidingFileSystem{http.Dir(".")} + http.Handle("/", http.FileServer(fs)) + log.Fatal(http.ListenAndServe(":8080", nil)) +} -- 2.50.0