@@ -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)
@@ -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)