package main import ( "net/http" "io" "os" "path/filepath" "log" "encoding/json" "fmt" ) func uploadHandler(config Conf) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { http.Error(w, "method not supported", http.StatusMethodNotAllowed) return } archType := r.URL.Query().Get("arch") if archType == "" { archType = "all" } distroName := r.URL.Query().Get("distro") if distroName == "" { distroName = "stable" } key := r.URL.Query().Get("key") if key == "" || key != config.Key { http.Error(w, "unauthorized", 403) return } reader, err := r.MultipartReader() if err != nil { httpErrorf(w, "error creating multipart reader: %s", err) return } for { part, err := reader.NextPart() if err == io.EOF { break } if part.FileName() == "" { continue } newPath := config.PoolPackagePath(distroName, archType, part.FileName()) if _, err := os.Stat(newPath); err != nil { if os.IsNotExist(err) { if err := os.MkdirAll(newPath, 0755); err != nil { httpErrorf(w, "error creating path: %s", err) return } } } dst, err := os.Create(filepath.Join(newPath, part.FileName())) if err != nil { httpErrorf(w, "error creating deb file: %s", err) return } defer dst.Close() if _, err := io.Copy(dst, part); err != nil { httpErrorf(w, "error writing deb file: %s", err) return } } mutex.Lock() defer mutex.Unlock() log.Println("got lock, updating package list...") if err := createPackagesGz(config, distroName, archType); err != nil { httpErrorf(w, "error creating package: %s", err) return } err = createRelease(config, distroName, archType) if err != nil { httpErrorf(w, "error creating package: %s", err) return } w.WriteHeader(http.StatusOK) }) } func deleteHandler(config Conf) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != "DELETE" { http.Error(w, "method not supported", http.StatusMethodNotAllowed) return } var toDelete DeleteObj if err := json.NewDecoder(r.Body).Decode(&toDelete); err != nil { httpErrorf(w, "failed to decode json: %s", err) return } debPath := filepath.Join(config.ArchPath(toDelete.DistroName, toDelete.Arch), toDelete.Filename) if err := os.Remove(debPath); err != nil { httpErrorf(w, "failed to delete: %s", err) return } key := r.URL.Query().Get("key") if key == "" || key != config.Key { http.Error(w, "unauthorized", http.StatusForbidden) return } mutex.Lock() defer mutex.Unlock() log.Println("got lock, updating package list...") if err := createPackagesGz(config, toDelete.DistroName, toDelete.Arch); err != nil { httpErrorf(w, "failed to delete package: %s", err) return } if err := createRelease(config, toDelete.DistroName, toDelete.Arch); err != nil { httpErrorf(w, "failed to delete package: %s", err) return } }) } func httpErrorf(w http.ResponseWriter, format string, a ...interface{}) { err := fmt.Errorf(format, a...) log.Println(err) http.Error(w, err.Error(), http.StatusInternalServerError) }