store: upload support

This commit is contained in:
Mikaël Cluseau 2019-10-16 17:58:48 +11:00
parent daa919e953
commit a7158e9e56

View File

@ -21,12 +21,13 @@ var (
) )
func main() { func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
flag.Parse() flag.Parse()
http.HandleFunc("/", handleHTTP) http.HandleFunc("/", handleHTTP)
log.Print("listening on ", *bind) log.Print("listening on ", *bind)
http.ListenAndServe(*bind, nil) log.Fatal(http.ListenAndServe(*bind, nil))
} }
func handleHTTP(w http.ResponseWriter, req *http.Request) { 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") defer log.Print(l, " done")
stat, err := os.Stat(filePath) stat, err := os.Stat(filePath)
if err != nil { if err != nil && !os.IsNotExist(err) {
writeErr(err, w) writeErr(err, w)
return return
} } else if err == nil && stat.Mode().IsDir() {
if stat.Mode().IsDir() {
http.NotFound(w, req) http.NotFound(w, req)
return return
} }
@ -59,8 +58,51 @@ func handleHTTP(w http.ResponseWriter, req *http.Request) {
http.ServeFile(w, req, filePath) http.ServeFile(w, req, filePath)
case "POST": case "POST":
// TODO upload tmpOut := filepath.Join(filepath.Dir(filePath), "."+filepath.Base(filePath))
http.Error(w, "not implemented", http.StatusNotImplemented)
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: default:
http.NotFound(w, req) http.NotFound(w, req)
@ -75,7 +117,7 @@ func writeErr(err error, w http.ResponseWriter) {
return return
} }
log.Print("internal error: ", err) log.Output(2, fmt.Sprint("internal error: ", err))
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Internal error\n")) w.Write([]byte("Internal error\n"))
} }