├── .gitignore ├── README.txt └── fileserver.go /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Simplest file server to (temporarily) serve static content from a local filesystem. 2 | 3 | Usage: 4 | 5 | fileserver [-a host:port] [pattern:]dir ... 6 | 7 | The program serves files from a local dist using dir argument as root. 8 | An optional pattern specified the URL base path. For instance, 9 | to serve /tmp dir at /temporary, one can use the following: 10 | 11 | fileserver /temporary:/tmp 12 | 13 | The dir argument can be specified multiple times. 14 | If no dir argument is provided, current directory is used. 15 | 16 | -a string 17 | Address (host:port) to listen on (default "localhost:8000") 18 | -------------------------------------------------------------------------------- /fileserver.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "log" 6 | "net/http" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | const usageText = `Usage: fileserver [-a host:port] [pattern:]dir ... 12 | 13 | The program serves files from a local dist using dir argument as root. 14 | An optional pattern specified the URL base path. For instance, 15 | to serve /tmp dir at /temporary, one can use the following: 16 | 17 | fileserver /temporary:/tmp 18 | 19 | The dir argument can be specified multiple times. 20 | If no dir argument is provided, current directory is used. 21 | 22 | ` 23 | 24 | var address *string = flag.String("a", "localhost:8000", "Address (host:port) to listen on") 25 | 26 | func main() { 27 | flag.Usage = func() { 28 | os.Stderr.WriteString(usageText) 29 | flag.PrintDefaults() 30 | } 31 | flag.Parse() 32 | roots := flag.Args() 33 | if len(roots) == 0 { 34 | roots = append(roots, ".") 35 | } 36 | for _, r := range roots { 37 | var p string 38 | if i := strings.IndexRune(r, ':'); i >= 0 { 39 | p = r[:i] 40 | r = r[i+1:] 41 | } 42 | if !strings.HasPrefix(p, "/") { 43 | p = "/" + p 44 | } 45 | fs := http.FileServer(http.Dir(r)) 46 | if len(p) > 1 { 47 | fs = http.StripPrefix(p, fs) 48 | } 49 | http.Handle(p, fs) 50 | } 51 | 52 | log.Printf("serving %s on http://%s", roots, *address) 53 | log.Fatal(http.ListenAndServe(*address, http.HandlerFunc(handle))) 54 | } 55 | 56 | func handle(w http.ResponseWriter, r *http.Request) { 57 | log.Printf("%s %s", r.Method, r.RequestURI) 58 | http.DefaultServeMux.ServeHTTP(w, r) 59 | } 60 | --------------------------------------------------------------------------------