aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go165
1 files changed, 114 insertions, 51 deletions
diff --git a/main.go b/main.go
index e8e1f02..dbbc888 100644
--- a/main.go
+++ b/main.go
@@ -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
+}