96 lines
2.4 KiB
Go
96 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
"path/filepath"
|
|
"os"
|
|
)
|
|
|
|
func main() {
|
|
port := flag.String("p", "8080", "Http listen port")
|
|
staticDirectory := flag.String("s", "static", "Static directory content")
|
|
docsDirectory := flag.String("docs", "", "Docs directory content")
|
|
dataDirectory := flag.String("data", "", "Data directory content")
|
|
trace := flag.Bool("trace", false, "Produce trace logs")
|
|
flag.Parse()
|
|
|
|
if *trace == true {
|
|
log.Printf("static folder: %s\n", *staticDirectory)
|
|
log.Printf("data folder: %s\n", *dataDirectory)
|
|
log.Printf("docs folder: %s\n", *docsDirectory)
|
|
}
|
|
|
|
http.HandleFunc("/data/", func( res http.ResponseWriter, req *http.Request ) {
|
|
safePath := ValidatePath(filepath.FromSlash(req.URL.Path[1:]))
|
|
if (*dataDirectory != "") {
|
|
safePath = filepath.FromSlash(filepath.Join(*dataDirectory, strings.Replace(safePath, "data/", "", 1)))
|
|
}
|
|
http.ServeFile(res, req, safePath)
|
|
})
|
|
|
|
http.HandleFunc("/docs/", func( res http.ResponseWriter, req *http.Request ) {
|
|
localPath := ""
|
|
if (*docsDirectory == "") {
|
|
temp := "../../.."
|
|
docsDirectory = &temp
|
|
localPath = ValidatePath(filepath.FromSlash(*docsDirectory+req.URL.Path))
|
|
} else {
|
|
localPath = ValidatePath(filepath.FromSlash(*docsDirectory+strings.Replace(req.URL.Path, "docs/", "", 1)))
|
|
}
|
|
if *trace == true {
|
|
log.Printf("fetch docs: \"%s\"", localPath)
|
|
}
|
|
f, err := os.Open(localPath)
|
|
if err != nil {
|
|
log.Printf("fetch docs error: \"%s\" with %s", localPath, err)
|
|
http.ServeFile(res, req, filepath.FromSlash(*staticDirectory + "/404.html"));
|
|
} else {
|
|
s, err := f.Stat()
|
|
if err != nil || s.IsDir() {
|
|
log.Printf("fetch docs stat error: \"%s\"", localPath)
|
|
http.ServeFile(res, req, filepath.FromSlash(*staticDirectory + "/404.html"))
|
|
} else {
|
|
http.ServeFile(res, req, localPath)
|
|
}
|
|
}
|
|
})
|
|
|
|
fileServer := http.FileServer(FileSystem{http.Dir(*staticDirectory)})
|
|
http.Handle("/", fileServer)
|
|
|
|
log.Printf("Serving on HTTP port: %s\n", *port)
|
|
log.Fatal(http.ListenAndServe(":"+*port, nil))
|
|
}
|
|
|
|
|
|
|
|
type FileSystem struct {
|
|
fs http.FileSystem
|
|
}
|
|
|
|
func (fs FileSystem) Open(path string) (http.File, error) {
|
|
f, err := fs.fs.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s, err := f.Stat()
|
|
if s.IsDir() {
|
|
index := strings.TrimSuffix(path, "/") + "/index.html"
|
|
if _, err := fs.fs.Open(index); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return f, nil
|
|
}
|
|
|
|
func ValidatePath(path string) string {
|
|
|
|
safePath := path
|
|
|
|
return safePath
|
|
} |