diff --git a/cmd/root.go b/cmd/root.go index 89eeeb6..a60e8db 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,7 +17,7 @@ var ( ) const ( - Version string = "0.57.6" + Version string = "0.58.0" ) var ( @@ -28,6 +28,7 @@ var ( filtering bool maximumFileCount uint32 minimumFileCount uint32 + pageLength uint16 port uint16 profile bool recursive bool @@ -80,6 +81,7 @@ func init() { rootCmd.Flags().BoolVarP(&filtering, "filter", "f", false, "enable filtering") rootCmd.Flags().Uint32Var(&maximumFileCount, "maximum-files", 1<<32-1, "skip directories with file counts over this value") rootCmd.Flags().Uint32Var(&minimumFileCount, "minimum-files", 0, "skip directories with file counts under this value") + rootCmd.Flags().Uint16Var(&pageLength, "page-length", 0, "pagination length for stats page") rootCmd.Flags().Uint16VarP(&port, "port", "p", 8080, "port to listen on") rootCmd.Flags().BoolVar(&profile, "profile", false, "register net/http/pprof handlers") rootCmd.Flags().BoolVarP(&recursive, "recursive", "r", false, "recurse into subdirectories") diff --git a/cmd/web.go b/cmd/web.go index 37088d7..1d77756 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -260,16 +260,34 @@ func (s *ServeStats) toImported(stats *exportedServeStats) { s.mutex.Unlock() } -func (s *ServeStats) ListImages() ([]byte, error) { +func (s *ServeStats) ListImages(page int) ([]byte, error) { stats := s.toExported() sort.SliceStable(stats.List, func(p, q int) bool { return strings.ToLower(stats.List[p]) < strings.ToLower(stats.List[q]) }) - a := make([]timesServed, len(stats.List)) + var startIndex, stopIndex int - for k, v := range stats.List { + if page == -1 { + startIndex = 0 + stopIndex = len(stats.List) - 1 + } else { + startIndex = ((page - 1) * int(pageLength)) + stopIndex = (startIndex + int(pageLength)) + } + + if startIndex > len(stats.List)-1 { + return []byte("{}"), nil + } + + if stopIndex > len(stats.List)-1 { + stopIndex = len(stats.List) - 1 + } + + a := make([]timesServed, stopIndex-startIndex) + + for k, v := range stats.List[startIndex:stopIndex] { a[k] = timesServed{v, stats.Count[v], stats.Size[v], stats.Times[v]} } @@ -567,7 +585,12 @@ func serveStats(args []string, stats *ServeStats) httprouter.Handle { startTime := time.Now() - response, err := stats.ListImages() + page, err := strconv.Atoi(r.URL.Query().Get("page")) + if err != nil || page == 0 { + page = -1 + } + + response, err := stats.ListImages(page) if err != nil { fmt.Println(err) @@ -593,7 +616,7 @@ func serveStats(args []string, stats *ServeStats) httprouter.Handle { } } -func serveDebugHtml(args []string, index *Index) httprouter.Handle { +func serveDebugHtml(args []string, index *Index, paginate bool) httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { w.Header().Set("Content-Type", "text/html") @@ -601,6 +624,26 @@ func serveDebugHtml(args []string, index *Index) httprouter.Handle { indexDump := index.Index() + var startIndex, stopIndex int + + page, err := strconv.Atoi(p.ByName("page")) + + if err != nil || page <= 0 { + startIndex = 0 + stopIndex = len(indexDump) - 1 + } else { + startIndex = ((page - 1) * int(pageLength)) + stopIndex = (startIndex + int(pageLength)) + } + + if startIndex > len(indexDump)-1 { + indexDump = []string{} + } + + if stopIndex > len(indexDump)-1 { + stopIndex = len(indexDump) - 1 + } + fileCount := strconv.Itoa(len(indexDump)) sort.SliceStable(indexDump, func(p, q int) bool { @@ -613,14 +656,34 @@ func serveDebugHtml(args []string, index *Index) httprouter.Handle { htmlBody.WriteString(``) htmlBody.WriteString(fmt.Sprintf("Index contains %s files", fileCount)) - for _, v := range indexDump { - var shouldSort = "" + if len(indexDump) > 0 { + for _, v := range indexDump[startIndex:stopIndex] { + var shouldSort = "" - if sorting { - shouldSort = "?sort=asc" + if sorting { + shouldSort = "?sort=asc" + } + htmlBody.WriteString(fmt.Sprintf("\n", ImagePrefix, v, shouldSort, v)) } - htmlBody.WriteString(fmt.Sprintf("\n", ImagePrefix, v, shouldSort, v)) } + if pageLength != 0 { + nextPage := page + 1 + if nextPage > (len(indexDump) / int(pageLength)) { + fmt.Printf("Nextpage (%d) is larger than end of index (%d)\n", nextPage, (len(indexDump) / int(pageLength))) + nextPage = len(indexDump) / int(pageLength) + } + + prevPage := page - 1 + if prevPage < 1 { + prevPage = 1 + } + + if paginate { + htmlBody.WriteString(fmt.Sprintf("", prevPage)) + htmlBody.WriteString(fmt.Sprintf("", nextPage)) + } + } + htmlBody.WriteString(`
%s
%s
`) b, err := io.WriteString(w, gohtml.Format(htmlBody.String())) @@ -651,7 +714,27 @@ func serveDebugJson(args []string, index *Index) httprouter.Handle { return strings.ToLower(indexDump[p]) < strings.ToLower(indexDump[q]) }) - response, err := json.MarshalIndent(indexDump, "", " ") + var startIndex, stopIndex int + + page, err := strconv.Atoi(p.ByName("page")) + + if err != nil || page <= 0 { + startIndex = 0 + stopIndex = len(indexDump) - 1 + } else { + startIndex = ((page - 1) * int(pageLength)) + stopIndex = (startIndex + int(pageLength)) + } + + if startIndex > len(indexDump)-1 { + indexDump = []string{} + } + + if stopIndex > len(indexDump)-1 { + stopIndex = len(indexDump) - 1 + } + + response, err := json.MarshalIndent(indexDump[startIndex:stopIndex], "", " ") if err != nil { fmt.Println(err) @@ -1037,9 +1120,15 @@ func ServePage(args []string) error { } if debug { - mux.GET("/html", serveDebugHtml(args, index)) + mux.GET("/html/", serveDebugHtml(args, index, false)) + if pageLength != 0 { + mux.GET("/html/:page", serveDebugHtml(args, index, true)) + } mux.GET("/json", serveDebugJson(args, index)) + if pageLength != 0 { + mux.GET("/json/:page", serveDebugJson(args, index)) + } } if profile { @@ -1067,6 +1156,9 @@ func ServePage(args []string) error { } mux.GET("/stats", serveStats(args, stats)) + if pageLength != 0 { + mux.GET("/stats/:page", serveStats(args, stats)) + } } err = srv.ListenAndServe()