Add uploadability

master v0.2
bel 2020-03-23 03:12:28 +00:00
parent 36cf5eee3e
commit 7c67df0f1d
1 changed files with 97 additions and 4 deletions

101
main.go
View File

@ -9,15 +9,28 @@ listing file.
package main
import (
"errors"
"fmt"
"io"
"local/args"
"local/gziphttp"
"log"
"net/http"
"os"
"path"
"strings"
)
const (
ENDPOINT_UPLOAD = "__upload__"
)
var (
fs *args.ArgSet
)
func main() {
fs := args.NewArgSet()
fs = args.NewArgSet()
fs.Append(args.STRING, "p", "port to serve", "8100")
fs.Append(args.STRING, "d", "static path to serve", "./public")
if err := fs.Parse(); err != nil {
@ -34,14 +47,94 @@ func main() {
log.Fatal(http.ListenAndServe(":"+p, nil))
}
func handler(d string) func(http.ResponseWriter, *http.Request) {
h := http.FileServer(http.Dir(d))
func handler(d string) http.HandlerFunc {
return gzip(endpoints(fserve(d)))
}
func writeMeta(w http.ResponseWriter) {
fmt.Fprintf(w, `
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
`)
}
func writeForm(w http.ResponseWriter) {
fmt.Fprintf(w, `
<form enctype="multipart/form-data" action="./%s" method="post">
<input type="file" name="file" required/>
<input type="submit" value="upload"/>
</form>
`, 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
}
h.ServeHTTP(w, r)
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 {
foo(w, r)
}
}
}
func isUploaded(r *http.Request) bool {
return path.Base(r.URL.Path) == ENDPOINT_UPLOAD
}
func isDir(r *http.Request) bool {
d := toRealPath(r.URL.Path)
fi, err := os.Stat(d)
return err == nil && fi.IsDir()
}
func fserve(d string) http.HandlerFunc {
h := http.FileServer(http.Dir(d))
return h.ServeHTTP
}
func upload(w http.ResponseWriter, r *http.Request) error {
r.ParseMultipartForm(100 << 20)
file, handler, err := r.FormFile("file")
if err != nil {
return err
}
defer file.Close()
p := toRealPath(path.Join(path.Dir(r.URL.Path), handler.Filename))
if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
return errors.New("already exists")
}
f, err := os.Create(p)
if err != nil {
return err
}
defer f.Close()
if _, err := io.Copy(f, file); err != nil {
return err
}
http.Redirect(w, r, path.Dir(r.URL.Path)+"/", http.StatusSeeOther)
return nil
}
func toRealPath(p string) string {
d := path.Join(fs.Get("d").GetString())
return path.Join(d, p)
}