diff options
Diffstat (limited to 'main.go')
| -rw-r--r-- | main.go | 165 |
1 files changed, 114 insertions, 51 deletions
@@ -17,6 +17,7 @@ import ( "net/url" "os" "path/filepath" + "sort" "strconv" "strings" "time" @@ -191,8 +192,8 @@ func (a *App) Handler() http.Handler { mux := http.NewServeMux() secHandlers := map[string]http.Handler{ - "/new": a.HandleNew(), - "/list": a.HandleList(), + "/api/v0/new": a.HandleNew(), + "/api/v0/list": a.HandleList(), "/api/v1/new": a.HandleNewJSON(), "/api/v1/list": a.HandleListJSON(), @@ -203,8 +204,8 @@ func (a *App) Handler() http.Handler { "/api/v1/view/", a.HandleViewJSON()), - "/view/": http.StripPrefix( - "/view/", + "/api/v0/view/": http.StripPrefix( + "/api/v0/view/", a.HandleViewPlain()), "/": http.FileServer(http.FS(a.static)), @@ -361,7 +362,7 @@ func (a *App) HandleNewJSON() http.Handler { return } - _, err = io.Copy(fh, bytes.NewBufferString(p.Content)) + _, err = fh.Write([]byte(p.Content)) if err != nil { sendErr(errResp{w, http.StatusInternalServerError, "Internal server error"}) return @@ -410,73 +411,135 @@ func (a *App) HandleViewPlain() http.Handler { }) } + func (a *App) HandleList() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - buf := &bytes.Buffer{} - - de, err := os.ReadDir(a.storage) + pl, err := LoadPastes(a.storage) if err != nil { sendErr(errResp{w, http.StatusInternalServerError, "Internal server error"}) return } - for _, e := range de { - if e.IsDir() { - continue - } - - info, err := e.Info() - if err != nil { - sendErr(errResp{w, http.StatusInternalServerError, "Internal server error"}) - return - } - - _, _ = buf.Write([]byte(fmt.Sprintf("%d\t%s\t%s\n", - info.Size(), - info.ModTime().Format("2006-01-02 15:04 MST"), - e.Name()))) + pl = handleSkipLimitSort(pl, r.URL) + + for _, e := range pl { + _, _ = w.Write([]byte(fmt.Sprintf("%d\t%s\t%s\n", + e.Size, + e.Created.Format("2006-01-02 15:04 MST"), + e.Id))) + } + }) +} + +func (a *App) HandleListJSON() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + pl, err := LoadPastes(a.storage) + if err != nil { + sendErr(errResp{w, http.StatusInternalServerError, + "Internal server error"}) + return } - _, _ = io.Copy(w, buf) + pl = handleSkipLimitSort(pl, r.URL) + + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + _ = enc.Encode(pl) }) } -type PasteListing struct { +type Paste struct { Id string `json:"id"` Created time.Time `json:"created"` Size int64 `json:"size"` } -func (a *App) HandleListJSON() http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - enc := json.NewEncoder(w) - enc.SetIndent("", " ") - out := []*PasteListing{} +type PasteListing []*Paste - de, err := os.ReadDir(a.storage) - if err != nil { - sendErr(errResp{w, http.StatusInternalServerError, "Internal server error"}) - return +func LoadPastes(pth string) (PasteListing, error) { + out := PasteListing{} + + de, err := os.ReadDir(pth) + if err != nil { + return nil, err + } + + for _, e := range de { + if e.IsDir() { + continue } - for _, e := range de { - if e.IsDir() { - continue - } - - info, err := e.Info() - if err != nil { - sendErr(errResp{w, http.StatusInternalServerError, "Internal server error"}) - return - } - - out = append(out, &PasteListing{ - e.Name(), - info.ModTime(), - info.Size(), - }) + info, err := e.Info() + if err != nil { + return nil, err } - _ = enc.Encode(out) + out = append(out, &Paste{ + Id: e.Name(), + Created: info.ModTime(), + Size: info.Size(), + }) + } + + out.SortDate() + return out, nil +} + +func (pl PasteListing) SortDateReverse() { + sort.Slice(pl, func(i, j int) bool { + return pl[i].Created.Before(pl[j].Created) }) } + +func (pl PasteListing) SortDate() { + sort.Slice(pl, func(i, j int) bool { + return pl[i].Created.After(pl[j].Created) + }) +} + +func getInt(u *url.URL, param string) (int, error) { + i := u.Query().Get(param) + if i == "" { + return 0, fmt.Errorf("No param '%s' supplied", param) + } + + n, err := strconv.Atoi(i) + if err != nil { + return 0, err + } + + return n, nil +} + +func limitSlice[T any](s []T, nElem int) []T { + if nElem > len(s) { + return s + } + return s[:nElem] +} + +func skipSlice[T any](s []T, skip int) []T { + if skip > len(s) { + return []T{} + } + + return s[skip:] +} + +func handleSkipLimitSort(pl PasteListing, URL *url.URL) PasteListing { + if _, ok := URL.Query()["reverse"] ; ok { + pl.SortDateReverse() + } + + skip, err := getInt(URL, "skip") + if err == nil { + pl = skipSlice(pl, skip) + } + + limit, err := getInt(URL, "limit") + if err == nil { + pl = limitSlice(pl, limit) + } + + return pl +} |
