From a7158e9e56a526dfe8d8d7494afb0d975961b001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Cluseau?= Date: Wed, 16 Oct 2019 17:58:48 +1100 Subject: [PATCH] store: upload support --- cmd/dkl-store/main.go | 58 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/cmd/dkl-store/main.go b/cmd/dkl-store/main.go index 7b93c7c..807249d 100644 --- a/cmd/dkl-store/main.go +++ b/cmd/dkl-store/main.go @@ -21,12 +21,13 @@ var ( ) func main() { + log.SetFlags(log.LstdFlags | log.Lshortfile) flag.Parse() http.HandleFunc("/", handleHTTP) log.Print("listening on ", *bind) - http.ListenAndServe(*bind, nil) + log.Fatal(http.ListenAndServe(*bind, nil)) } func handleHTTP(w http.ResponseWriter, req *http.Request) { @@ -37,12 +38,10 @@ func handleHTTP(w http.ResponseWriter, req *http.Request) { defer log.Print(l, " done") stat, err := os.Stat(filePath) - if err != nil { + if err != nil && !os.IsNotExist(err) { writeErr(err, w) return - } - - if stat.Mode().IsDir() { + } else if err == nil && stat.Mode().IsDir() { http.NotFound(w, req) return } @@ -59,8 +58,51 @@ func handleHTTP(w http.ResponseWriter, req *http.Request) { http.ServeFile(w, req, filePath) case "POST": - // TODO upload - http.Error(w, "not implemented", http.StatusNotImplemented) + tmpOut := filepath.Join(filepath.Dir(filePath), "."+filepath.Base(filePath)) + + if err := os.MkdirAll(filepath.Dir(filePath), 0755); err != nil { + writeErr(err, w) + return + } + + out, err := os.Create(tmpOut) + if err != nil { + writeErr(err, w) + return + } + + h := sha1.New() + mw := io.MultiWriter(out, h) + + _, err = io.Copy(mw, req.Body) + out.Close() + + if err != nil { + os.Remove(tmpOut) + + writeErr(err, w) + return + } + + sha1Hex := hex.EncodeToString(h.Sum(nil)) + log.Print("upload SHA1: ", sha1Hex) + + reqSHA1 := req.Header.Get("X-Content-SHA1") + if reqSHA1 != "" && reqSHA1 != sha1Hex { + err = fmt.Errorf("upload SHA1 does not match given SHA1: %s", reqSHA1) + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(err.Error() + "\n")) + return + } + + os.Rename(tmpOut, filePath) + + if err := ioutil.WriteFile(filePath+".sha1", []byte(sha1Hex), 0644); err != nil { + writeErr(err, w) + return + } + + w.WriteHeader(http.StatusCreated) default: http.NotFound(w, req) @@ -75,7 +117,7 @@ func writeErr(err error, w http.ResponseWriter) { return } - log.Print("internal error: ", err) + log.Output(2, fmt.Sprint("internal error: ", err)) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Internal error\n")) }