package main import ( "errors" "flag" "io" "log" "math/rand" "net/http" "os" "path" "time" ) const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" func init() { rand.Seed(time.Now().UnixNano()) } // RandString taken from https://stackoverflow.com/a/31832326 func RandString(n int) string { b := make([]byte, n) for i := range b { b[i] = letterBytes[rand.Int63()%int64(len(letterBytes))] } return string(b) } var dataDirFlag = flag.String("dataDir", "/tmp", "directory for files") var domainFlag = flag.String("domain", "http://localhost:8085", "base domain") var bindFlag = flag.String("bind", ":8085", "host and port to bind") func main() { flag.Parse() h := &Handler{ DataDir: *dataDirFlag, Domain: *domainFlag, } log.Println("listening") panic(http.ListenAndServe(*bindFlag, h)) } type Handler struct { DataDir string Domain string } func (h *Handler) ServeHTTP(wr http.ResponseWriter, req *http.Request) { if req.Method != "POST" { return } name := RandString(8) for { _, err := os.Stat(path.Join(h.DataDir, name)) if errors.Is(err, os.ErrNotExist) { break } name = RandString(8) } file, err := os.OpenFile(path.Join(h.DataDir, name), os.O_CREATE|os.O_RDWR, 0o644) if err != nil { log.Println("error:", err) return } defer file.Close() defer req.Body.Close() _, err = io.Copy(file, req.Body) if err != nil { log.Println("error:", err) return } log.Println("uploaded as", name) wr.Write([]byte(h.Domain + "/" + name + "\n")) }