From b9bb17044a8c2b47c7e96660e27ab645f82bec9d Mon Sep 17 00:00:00 2001 From: Mitch Riedstra Date: Thu, 4 Mar 2021 19:44:02 -0500 Subject: Further refactoring. --- cmd/web/handlers.go | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 cmd/web/handlers.go (limited to 'cmd/web/handlers.go') diff --git a/cmd/web/handlers.go b/cmd/web/handlers.go new file mode 100644 index 0000000..b8fa705 --- /dev/null +++ b/cmd/web/handlers.go @@ -0,0 +1,207 @@ +package main + +import ( + "fmt" + "strings" + "net/url" + "os" + "encoding/json" + "io" + "net/http" + "time" + + "github.com/gorilla/mux" + "riedstra.dev/mitch/steam-export/steam" +) + +func (a *App) HandleIndex(w http.ResponseWriter, r *http.Request) { + // During rendering of the template I believe it's + // mutating during the sort of keys, so Lib no longer + // is an RWMutex and we're just locking this as if + // we're writing to it + a.Library.Lock() + defer a.Library.Unlock() + a.Status.Lock() + defer a.Status.Unlock() + + err := a.Templates.ExecuteTemplate(w, "index", + struct { + Lib *steam.Library + Info *statusInfo + Local bool + HostIP string + Port string + Version string + }{ + &a.Library.Library, + a.Status, + isLocal(r.RemoteAddr), + getHostIP(), + getPort(), + Version, + }) + if err != nil { + Logger.Printf("While Rendering template: %s", err) + } + Logger.Printf("Client %s Index page", r.RemoteAddr) +} + +func (a *App) HandleInstall(w http.ResponseWriter, r *http.Request) { + err := r.ParseForm() + if err != nil { + Logger.Printf("Installer: While parsing form: %s", err) + http.Error(w, fmt.Sprintf("Invalid form: %s", err), 400) + return + } + + uri := r.Form.Get("uri") + + if strings.HasPrefix(uri, "http") { + _, err := url.Parse(uri) + if err != nil { + Logger.Printf("Installer: While parsing url: %s", err) + http.Error(w, fmt.Sprintf("Invalid url: %s", err), 400) + return + } + } else { + fi, err := os.Stat(uri) + if err != nil || !fi.Mode().IsRegular() { + Logger.Printf("Installer: While parsing url/path: %s", err) + http.Error(w, fmt.Sprintf("Invalid uri/path: %s", err), 400) + return + } + } + + Logger.Printf("Installer: Sending request for: %s to channel", uri) + a.download <- uri + + http.Redirect(w, r, "/", 302) +} + +func (a *App) HandleDownload(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + game := vars["game"] + + a.Library.Lock() + g, ok := a.Library.Games[game] + a.Library.Unlock() + if !ok { + Logger.Printf("Missing: %s", game) + http.Error(w, "Game is missing", 404) + return + } + + w.Header().Add("Content-type", "application/tar") + w.Header().Add("Estimated-size", fmt.Sprintf("%d", g.Size)) + + Logger.Printf("Client %s is downloading: %s", r.RemoteAddr, game) + + // Invert the writer so we can break up the copy and get progress + // information in here + rdr, pwrtr := io.Pipe() + go func() { + err := g.Package(pwrtr) + if err != nil { + Logger.Println("Error in package writing: ", err) + } + }() + + var total int64 + start := time.Now() + for { + n, err := io.CopyN(w, rdr, 256*1024*1024) + if err == io.EOF { + break + } + if err != nil { + Logger.Printf("Client %s Error Sending game: %s", r.RemoteAddr, err) + // Headers already sent, don't bother sending an error + return + } + total += n + mb := float64(total / 1024 / 1024) + rate := mb / time.Since(start).Seconds() + + Logger.Printf("Client %s is downloading %s: %0.1f%% done %.2f mb/s", + r.RemoteAddr, game, float64(total)/float64(g.Size)*100, rate) + } + + Logger.Printf("Client %s finished downloading: %s", r.RemoteAddr, game) +} + +func (a *App) HandleDelete(w http.ResponseWriter, r *http.Request) { + err := r.ParseForm() + if err != nil { + Logger.Printf("Installer: While parsing form: %s", err) + http.Error(w, fmt.Sprintf("Invalid form: %s", err), 400) + return + } + + game := r.PostForm.Get("name") + + if game == "" { + Logger.Println("Deleter: No game specified") + http.Error(w, "Game param required", 400) + return + } + + a.Library.Lock() + g, ok := a.Library.Games[game] + a.Library.Unlock() + if !ok { + Logger.Printf("Missing: %s", game) + http.Error(w, "Game is missing", 404) + return + } + + err = g.Delete() + if err != nil { + Logger.Printf("Error removing game: %s", err) + http.Error(w, fmt.Sprintf("Error removing game: %s", err), 500) + return + } + Logger.Printf("Removed game: %s", game) + + a.LibraryReload() + http.Redirect(w, r, "/", 302) +} + +func (a *App) HandleStats(w http.ResponseWriter, r *http.Request) { + a.Status.RLock() + defer a.Status.RUnlock() + + w.Header().Add("Content-type", "application/json") + + enc := json.NewEncoder(w) + + err := enc.Encode(a.Status) + if err != nil { + Logger.Println("While encoding Status: ", err) + } + return +} + +func (a *App) HandleSetLib(w http.ResponseWriter, r *http.Request) { + err := r.ParseForm() + if err != nil { + Logger.Printf("Setlib: While parsing form: %s", err) + http.Error(w, fmt.Sprintf("Invalid form: %s", err), 400) + return + } + + a.LibrarySet(r.Form.Get("path")) + + http.Redirect(w, r, "/", 302) +} + +func HandleQuit(w http.ResponseWriter, r *http.Request) { + Logger.Println("Quit was called, exiting") + w.Header().Add("Content-type", "text/plain") + w.Write([]byte("Shutting down...")) + go func() { + time.Sleep(time.Second * 2) + os.Exit(0) + }() + return +} + -- cgit v1.2.3