-
Notifications
You must be signed in to change notification settings - Fork 0
/
file_list_handler.go
126 lines (108 loc) · 2.78 KB
/
file_list_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"fmt"
"github.com/pkg/errors"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"strings"
)
type fileListHandler struct {
servedDir string
}
type fileListRequest struct {
servedDir string
fileType string
recursive bool
startsWith string
response http.ResponseWriter
}
func NewFileListHandler(servedDir string) http.Handler {
return &fileListHandler{servedDir: servedDir}
}
func (h *fileListHandler) ServeHTTP(response http.ResponseWriter, request *http.Request) {
query := request.URL.Query()
query.Add("type", "file")
query.Add("recursive", "yes")
fileType := query.Get("type")
if err := h.checkParamater("type", fileType, "any", "file", "dir"); err != nil {
response.WriteHeader(http.StatusBadRequest)
fmt.Fprint(response, err)
return
}
recursive := query.Get("recursive")
if err := h.checkParamater("recursive", recursive, "yes", "no"); err != nil {
response.WriteHeader(http.StatusBadRequest)
fmt.Fprint(response, err)
return
}
listRequest := fileListRequest{
servedDir: h.servedDir,
fileType: fileType,
recursive: recursive == "yes",
startsWith: query.Get("startswith"),
response: response,
}
listRequest.Handle()
}
func (h *fileListHandler) checkParamater(name string, value string, validValues ...string) error {
for _, validValue := range validValues {
if value == validValue {
return nil
}
}
return errors.Errorf("'%s' is not a valid option for '%s' parameter\n", name, value)
}
func (r *fileListRequest) Handle() {
dir := filepath.Join(r.servedDir, r.startsWith)
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
r.response.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(r.response, "'%s' is not an existing directory\n", r.startsWith)
return
}
if r.recursive {
r.printRecursive(dir)
} else {
r.printFlat(dir)
}
}
func (r *fileListRequest) printRecursive(startDir string) {
walkFunc := func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Printf("Error when walking served directory: %s\n", err)
return nil
}
r.printPath(path, info)
return nil
}
filepath.Walk(startDir, walkFunc)
}
func (r *fileListRequest) printFlat(startDir string) {
if files, err := ioutil.ReadDir(startDir); err == nil {
for _, file := range files {
r.printPath(filepath.Join(startDir, file.Name()), file)
}
} else {
r.response.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(r.response, err)
}
}
func (r *fileListRequest) printPath(path string, info os.FileInfo) {
switch r.fileType {
case "any":
r.writePath(path)
case "file":
if !info.IsDir() {
r.writePath(path)
}
case "dir":
if info.IsDir() {
r.writePath(path)
}
}
}
func (r *fileListRequest) writePath(path string) {
fmt.Fprintln(r.response, strings.TrimPrefix(path, r.servedDir))
}