-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
101 lines (85 loc) · 2.55 KB
/
main.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
package main
import (
"flag"
"fmt"
"net/http"
"path"
"strings"
"github.com/justinas/alice"
"github.com/spitzfaust/file-server/logger"
)
func check(err error, logger logger.Logger) {
if err != nil {
logger.Error("An error occurred: %s", err)
panic(err)
}
}
func cleanPrefix(prefix string) string {
cleanedPrefix := path.Clean(prefix)
if cleanedPrefix == "." {
cleanedPrefix = ""
}
cleanedPrefix += "/"
if !strings.HasPrefix(cleanedPrefix, "/") {
cleanedPrefix = "/" + cleanedPrefix
}
return cleanedPrefix
}
// ProgramName is the program name.
const ProgramName = "file-server"
// Program version. Is set automatically in the build process.
var version = "master"
var date = "Hallo"
func disableCaching(next http.Handler) http.Handler {
var etagHeaders = []string{
"ETag",
"If-Modified-Since",
"If-Match",
"If-None-Match",
"If-Range",
"If-Unmodified-Since",
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
for _, h := range etagHeaders {
w.Header().Del(h)
}
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "0")
next.ServeHTTP(w, r)
})
}
func main() {
port := flag.String("p", "8100", "port to serve on")
prefix := flag.String("f", "", "path under which files should be exposed (e.g. /files/img)")
directory := flag.String("d", ".", "directory of static files on host (e.g. ./documents)")
showVersion := flag.Bool("v", false, "display the version")
caching := flag.Bool("c", false, "enable client caching headers")
verbose := flag.Bool("l", false, "enable detailed logs")
flag.Parse()
l := logger.NewLoggerWithLevel(logger.Info)
if *verbose {
l.SetLogLevel(logger.Debug)
}
l.Debug("Port set to: %s", *port)
l.Debug("Prefix set to: %s", *prefix)
l.Debug("Directory set to: %s", *directory)
l.Debug("Version set to %t", *showVersion)
l.Debug("Caching set to: %t", *caching)
l.Debug("Verbose set to: %t", *verbose)
if *showVersion {
fmt.Printf("%s\nVersion: %s\nBuilt on: %s\n", ProgramName, version, date)
return
}
finalHandler := http.FileServer(http.Dir(*directory))
cleanedPrefix := cleanPrefix(*prefix)
middlewareChain := alice.New(l.Middleware)
if !*caching {
middlewareChain = middlewareChain.Append(disableCaching)
}
http.Handle(cleanedPrefix, middlewareChain.Then(http.StripPrefix(cleanedPrefix, finalHandler)))
l.Info("Serving %s on HTTP port: %s\n", *directory, *port)
l.Info("Visit: http://localhost:%s%s", *port, cleanedPrefix)
err := http.ListenAndServe(":"+*port, nil)
check(err, l)
}