package main import ( "bytes" "errors" "fmt" "io" "io/ioutil" "local/args" "local/gziphttp" "local/notes-server/notes/md" "local/simpleserve/simpleserve" "log" "net/http" "net/http/httptest" "os" "path" "regexp" "strings" ) const ( ENDPOINT_UPLOAD = "__upload__" ENDPOINT_DELETE = "__delete__" ) var ( fs *args.ArgSet ) func main() { fs = args.NewArgSet() fs.Append(args.STRING, "p", "port to serve", "8100") fs.Append(args.BOOL, "md", "whether to render markdown as html", true) fs.Append(args.STRING, "md-css", "css to load for md", "./public/bundle.css") fs.Append(args.STRING, "md-class", "class to wrap md", "phb") fs.Append(args.STRING, "d", "static path to serve", "./public") if err := fs.Parse(); err != nil { panic(err) } d := fs.Get("d").GetString() md := fs.Get("md").GetBool() mdCss := fs.Get("md-css").GetString() mdClass := fs.Get("md-class").GetString() if mdCss != "" { b, err := ioutil.ReadFile(mdCss) if err != nil { panic(err) } mdCss = fmt.Sprintf(` `, mdClass, mdClass, b, ) } p := strings.TrimPrefix(fs.Get("p").GetString(), ":") http.Handle("/", http.HandlerFunc(handler(d, md, mdCss, mdClass))) log.Printf("Serving %s on HTTP port: %s\n", d, p) log.Fatal(http.ListenAndServe(":"+p, nil)) } func handler(d string, md bool, mdCss, mdClass string) http.HandlerFunc { return gzip(endpoints(withDel(withMD(d, md, mdCss, mdClass, fserve(d))))) } func writeMeta(w http.ResponseWriter) { fmt.Fprintf(w, `
`) } func writeForm(w http.ResponseWriter) { fmt.Fprintf(w, ` `, ENDPOINT_UPLOAD) } func gzip(foo http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if gziphttp.Can(r) { gz := gziphttp.New(w) defer gz.Close() w = gz } foo(w, r) } } func endpoints(foo http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if isDir(r) { writeMeta(w) writeForm(w) } if isUploaded(r) { if err := upload(w, r); err != nil { fmt.Fprintln(w, err.Error()) } } else if isDeleted(r) { if err := del(w, r); err != nil { fmt.Fprintln(w, err.Error()) } } else { simpleserve.SetContentTypeIfMedia(w, r) foo(w, r) } } } func isUploaded(r *http.Request) bool { return path.Base(r.URL.Path) == ENDPOINT_UPLOAD } func isDeleted(r *http.Request) bool { return path.Base(r.URL.Path) == ENDPOINT_DELETE } func isDir(r *http.Request) bool { d := toRealPath(r.URL.Path) fi, err := os.Stat(d) if err != nil { return false } if !fi.IsDir() { return false } if _, err := os.Stat(path.Join(d, "index.html")); err == nil { return false } return true } func withMD(dir string, enabled bool, mdCss, mdClass string, foo http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { realpath := toRealPath(r.URL.Path) if enabled && !isDir(r) && path.Ext(realpath) == ".md" { b, err := ioutil.ReadFile(realpath) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } s, err := md.Gomarkdown(b, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } fmt.Fprintln(w, mdCss) fmt.Fprintf(w, "