diff --git a/helperfuncs.go b/helperfuncs.go index 68eab55ce335872306ef942bdfd37ebf44c8d060..2c94a061b8e28d37954b18cca7bac9b40e3e0356 100644 --- a/helperfuncs.go +++ b/helperfuncs.go @@ -5,6 +5,7 @@ package main import ( + "errors" "fmt" "log" "strings" @@ -28,6 +29,48 @@ func (m model) create(name string, url string) string { return fmt.Sprint("URL mapped to ", name, "\n") } +// read() accepts a start variable for the first link in a set (implying reverse +// iteration), an end variable for the last link in a set (implying forward +// iteration), and a count variable for the number of requested entries. The +// requested set is returned as JSON. +func (m model) read(start string, end string, count int) (map[string]string, error) { + links := make(map[string]string) + + if !(count > 0) { + return nil, errors.New("Count parameter is required") + } + + err := m.database.View(func(txn *badger.Txn) error { + opts := badger.DefaultIteratorOptions + opts.PrefetchSize = 10 + if start != "" && end == "" { + opts.Reverse = true + } + iterator := txn.NewIterator(opts) + if start != "" && end == "" { + iterator.Seek([]byte(end)) + } else if start == "" && end != "" { + iterator.Seek([]byte(start)) + } + defer iterator.Close() + for iterator.Rewind(); iterator.Valid(); iterator.Next() { + err := iterator.Item().Value(func(v []byte) error { + links[string(iterator.Item().Key())] = string(v) + return nil + }) + if err != nil { + return err + } + } + return nil + }) + if err != nil { + return nil, err + } + + return links, nil +} + // Update modifies a shortened link func (m model) update(name string, url string, oldName string) string { m.create(name, url) diff --git a/readHandler.go b/readHandler.go index beaf4f8087a6eacc1c408d13aaf615c8a38b6f43..98d217dd9cc19920b25e3fd554bb6a959e6431b5 100644 --- a/readHandler.go +++ b/readHandler.go @@ -8,9 +8,8 @@ import ( "encoding/json" "log" "net/http" + "strconv" "strings" - - "github.com/dgraph-io/badger/v3" ) func (m model) readHandler(writer http.ResponseWriter, request *http.Request) { @@ -18,38 +17,36 @@ func (m model) readHandler(writer http.ResponseWriter, request *http.Request) { token = strings.TrimPrefix(token, "Bearer ") if token != m.AccessToken { - http.Error(writer, "401 Unauthorized: You do not have permission to view shortlinks", 403) + http.Error(writer, "403 Forbidden: You do not have permission to view shortlinks", 403) return } - links := make(map[string]string) - - err := m.database.View(func(txn *badger.Txn) error { - opts := badger.DefaultIteratorOptions - opts.PrefetchSize = 10 - iterator := txn.NewIterator(opts) - defer iterator.Close() - for iterator.Rewind(); iterator.Valid(); iterator.Next() { - item := iterator.Item() - k := item.Key() - err := item.Value(func(v []byte) error { - links[string(k)] = string(v) - return nil - }) - if err != nil { - return err - } - } - return nil - }) + query := request.URL.Query() + + start := query.Get("start") + end := query.Get("end") + countQuery := query.Get("count") + if countQuery == "" { + http.Error(writer, "400 Bad Request: Count parameter is required", 400) + } + + count, err := strconv.Atoi(countQuery) if err != nil { - log.Println(err) + http.Error(writer, err.Error(), 400) + return + } + + links, err := m.read(start, end, count) + if err != nil { + http.Error(writer, err.Error(), 400) + return } json, err := json.Marshal(links) if err != nil { log.Println(err) } + _, err = writer.Write(json) if err != nil { log.Println(err)