|
package main |
|
|
|
// Serve a web page for files. |
|
// |
|
// To see cache behavior: curl -I localhost:8000/foo |
|
// See also: http FileServer example (DotFileHiding, StripPrefix), and Dir(). |
|
|
|
import ( |
|
"log" |
|
"net/http" |
|
"os" |
|
"path/filepath" |
|
"strings" |
|
) |
|
|
|
const port = ":8001" |
|
|
|
var baseDir = "." |
|
|
|
// Serve a file |
|
func handleServeFile(w http.ResponseWriter, r *http.Request) { |
|
|
|
// log.Printf("Got a request for serve file:%s\n", r.URL.Path) |
|
// log.Printf(" Method:%s\n", r.Method) |
|
// log.Printf(" Path:%s\n", r.URL.Path) |
|
// log.Printf(" Query:%v\n", r.URL.Query()) |
|
|
|
file := r.URL.Path |
|
|
|
// We guard against "..", which also disallows filename having two dots. |
|
// This is actually unnecessary since http.ServerFile also does a check, and |
|
// their check is smarter. |
|
if strings.Contains(file, "..") { |
|
log.Println("Disallowed:" + file) |
|
w.WriteHeader(http.StatusNotFound) |
|
return |
|
} |
|
|
|
path := filepath.Join(baseDir, file) |
|
log.Println(path) |
|
http.ServeFile(w, r, path) |
|
} |
|
|
|
func main() { |
|
log.SetFlags(log.Flags() | log.Lmicroseconds) |
|
|
|
if len(os.Args) == 2 { |
|
baseDir = os.Args[1] |
|
} else if len(os.Args) != 1 { |
|
log.Fatalf("Expecting either no arguments or the base directory") |
|
} |
|
|
|
// We must specify the baseDir as absolute, because ServeFile will reject |
|
// requests where r.URL.Path contains a ".." path element. |
|
log.Printf("Using as base directory::%s\n", baseDir) |
|
var err error |
|
baseDir, err = filepath.Abs(baseDir) |
|
if err != nil { |
|
log.Fatal("Cannot get absolute directory for the base directory:", baseDir) |
|
} |
|
log.Printf("Using as base directory::%s\n", baseDir) |
|
log.Printf("About to serve on port:%s\n", port) |
|
|
|
http.HandleFunc("/", handleServeFile) |
|
if err := http.ListenAndServe(port, nil); err != nil { |
|
panic(err) |
|
} |
|
} |