| @ -1,178 +0,0 @@ | |||
| package pypihub | |||
| import ( | |||
| "encoding/base64" | |||
| "fmt" | |||
| "io" | |||
| "net/http" | |||
| "strconv" | |||
| "strings" | |||
| "time" | |||
| ) | |||
| type Server struct { | |||
| client *Client | |||
| config Config | |||
| assets []Asset | |||
| timer *time.Timer | |||
| } | |||
| func NewServer(cfg Config) *Server { | |||
| return &Server{ | |||
| client: NewClient(cfg), | |||
| config: cfg, | |||
| assets: make([]Asset, 0), | |||
| } | |||
| } | |||
| func (s *Server) findAsset(owner string, repo string, id int) *Asset { | |||
| for _, a := range s.assets { | |||
| if a.Owner == owner && a.Repo == repo && a.ID == id { | |||
| return &a | |||
| } | |||
| } | |||
| return nil | |||
| } | |||
| func (s *Server) refetchAssets() { | |||
| var err error | |||
| s.assets, err = s.client.GetAllAssets() | |||
| if err != nil { | |||
| fmt.Println(err) | |||
| } | |||
| } | |||
| func (s *Server) startTimer() { | |||
| if s.timer != nil { | |||
| s.timer.Stop() | |||
| } | |||
| s.timer = time.AfterFunc(time.Duration(10*time.Minute), func() { | |||
| go s.refetchAssets() | |||
| }) | |||
| } | |||
| func (s *Server) listAssets(w http.ResponseWriter, r *http.Request) { | |||
| var repo = strings.Trim(r.URL.Path, "/") | |||
| w.Header().Add("Content-Type", "text/html") | |||
| fmt.Fprintf(w, "<html><title>Links for %s</title><meta name=\"api-version\" content=\"2\" /><body>", repo) | |||
| fmt.Fprintf(w, "<h1>Links for %s</h1>", repo) | |||
| for _, a := range s.assets { | |||
| if a.Repo == repo { | |||
| fmt.Fprintf(w, "<a href=\"%s\">%s</a> ", a.URL(), a.Name) | |||
| } | |||
| } | |||
| fmt.Fprintf(w, "</body></html>") | |||
| } | |||
| func (s *Server) listRepoAssets(w http.ResponseWriter, r *http.Request) { | |||
| var parts = strings.SplitN(strings.Trim(r.URL.Path, "/"), "/", 2) | |||
| var owner = parts[0] | |||
| var repo = parts[1] | |||
| w.Header().Add("Content-Type", "text/html") | |||
| fmt.Fprintf(w, "<html><title>Links for %s</title><meta name=\"api-version\" content=\"2\" /><body>", repo) | |||
| fmt.Fprintf(w, "<h1>Links for %s</h1>", repo) | |||
| for _, a := range s.assets { | |||
| if a.Owner == owner && a.Repo == repo { | |||
| fmt.Fprintf(w, "<a href=\"%s\">%s</a> ", a.URL(), a.Name) | |||
| } | |||
| } | |||
| fmt.Fprintf(w, "</body></html>") | |||
| } | |||
| func (s *Server) listAllAssets(w http.ResponseWriter, r *http.Request) { | |||
| w.Header().Add("Content-Type", "text/html") | |||
| fmt.Fprintf(w, "<html><title>All asset links</title><meta name=\"api-version\" content=\"2\" /><body>") | |||
| fmt.Fprintf(w, "<h1>All asset links</h1>") | |||
| for _, a := range s.assets { | |||
| fmt.Fprintf(w, "<a href=\"%s\">%s</a> ", a.URL(), a.Name) | |||
| } | |||
| fmt.Fprintf(w, "</body></html>") | |||
| } | |||
| func (s *Server) listRepos(w http.ResponseWriter, r *http.Request) { | |||
| w.Header().Add("Content-Type", "text/html") | |||
| fmt.Fprintf(w, "<html><title>Simple index</title><meta name=\"api-version\" content=\"2\" /><body>") | |||
| for _, r := range s.config.RepoNames { | |||
| var parts = strings.SplitN(r, "/", 2) | |||
| fmt.Fprintf(w, "<a href=\"/%s\">%s</a> ", parts[1], parts[1]) | |||
| } | |||
| fmt.Fprintf(w, "</body></html>") | |||
| } | |||
| func (s *Server) fetchAsset(w http.ResponseWriter, r *http.Request) { | |||
| var url = strings.Trim(r.URL.Path, "/") | |||
| var parts = strings.SplitN(url, "/", 4) | |||
| if len(parts) != 4 { | |||
| w.WriteHeader(http.StatusNotFound) | |||
| return | |||
| } | |||
| var asset *Asset | |||
| var id int64 | |||
| var err error | |||
| id, err = strconv.ParseInt(parts[2], 10, 32) | |||
| if err != nil { | |||
| w.WriteHeader(http.StatusNotFound) | |||
| return | |||
| } | |||
| asset = s.findAsset(parts[0], parts[1], int(id)) | |||
| if asset == nil { | |||
| w.WriteHeader(http.StatusNotFound) | |||
| return | |||
| } | |||
| var rc io.ReadCloser | |||
| rc, err = s.client.DownloadAsset(*asset) | |||
| if err != nil || rc == nil { | |||
| w.WriteHeader(http.StatusNotFound) | |||
| return | |||
| } | |||
| defer rc.Close() | |||
| io.Copy(w, rc) | |||
| } | |||
| func (s *Server) serveFavicon(w http.ResponseWriter, r *http.Request) { | |||
| var decoded []byte | |||
| var err error | |||
| decoded, err = base64.StdEncoding.DecodeString("AAABAAEAEBAAAAEACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAAAAAPs7/AJ9vNwBO3f8APMz/AEzb/wCdbjYAStn/AJZqNgBI1/8ARtX/AETT/wBA0f8AqnY3AD7P/wCjcjcApHI3ADzN/wBQ3v8AOsv/AE7c/wA4yf8Amm02ALF6OACYazYARtb/AETU/wCveTcAQtL/AKh1NwCtdzcAQND/AKFxNwCmczcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcDA4RExUAAAAAAAAAAAAZGhwfDhEAFQAAAAAAAAAACRkaHB8OABMAAAAAAAAAAAcJGRocHw4RAAAAAAAgAgYFBwkZGhwfARETFQAhDyACAwUHCQoaHB8BERMVHSEPIBIUBQcJChocHwEREw0dIQ8AEhQFBwkKGhwfAQQeDR0hDyACBhYYCAALHB8BGx4NHSEPIAIGFhgICgscHxcbHg0dIRAgAgYWGAkKCxwAFxseDR0hECACBhYHCQoAAAAAAB4NHSEQIAIGAAAAAAAAAAAbAA0dIRAgAgAAAAAAAAAAFwAeDR0hECAAAAAAAAAAAAAXGx4NHSEAAAAAAPgfAADwLwAA8C8AAPAPAACAAQAAAAAAAAAAAAAIAAAAABAAAAAAAAAAAAAAgAEAAPAPAAD0DwAA9A8AAPgfAAA=") | |||
| if err != nil { | |||
| w.WriteHeader(http.StatusNotFound) | |||
| return | |||
| } | |||
| fmt.Fprintf(w, "%s", decoded) | |||
| } | |||
| func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |||
| var parts = strings.Split(strings.Trim(r.URL.Path, "/"), "/") | |||
| parts = removeEmpty(parts) | |||
| fmt.Println(r.URL.Path) | |||
| switch len(parts) { | |||
| case 0: | |||
| s.listAllAssets(w, r) | |||
| case 1: | |||
| if parts[0] == "favicon.ico" { | |||
| s.serveFavicon(w, r) | |||
| } else { | |||
| s.listAssets(w, r) | |||
| } | |||
| case 2: | |||
| s.listRepoAssets(w, r) | |||
| default: | |||
| s.fetchAsset(w, r) | |||
| } | |||
| } | |||
| func (s *Server) ListenAndServe() error { | |||
| s.refetchAssets() | |||
| s.startTimer() | |||
| http.Handle("/", s) | |||
| fmt.Println("Server listening at", s.config.Bind) | |||
| return http.ListenAndServe(s.config.Bind, nil) | |||
| } | |||