github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/base/params/list.go (about) 1 // Package params defines generic input parameter structures 2 package params 3 4 import ( 5 "fmt" 6 "net/http" 7 "strconv" 8 "strings" 9 ) 10 11 var ( 12 // ErrListParamsNotEmpty indicates that there are list values in the params 13 ErrListParamsNotEmpty = fmt.Errorf("list params not empty") 14 // DefaultListLimit is the default value for a list 15 DefaultListLimit = 25 16 ) 17 18 // ListParams can pull list param information from an http.Request 19 type ListParams interface { 20 // ListParamsFromRequest pulls list params from the URL 21 ListParamsFromRequest(r *http.Request) error 22 } 23 24 // ListAll uses a limit of -1 & offset of 0 as a sentinel value for listing 25 // all items 26 var ListAll = List{Limit: -1} 27 28 // List defines input parameters for listing operations 29 type List struct { 30 Filter []string 31 OrderBy OrderBy 32 Limit int 33 Offset int 34 } 35 36 // ListParamsFromRequest satisfies the ListParams interface 37 func (lp *List) ListParamsFromRequest(r *http.Request) error { 38 l := List{} 39 limitStr := r.URL.Query().Get("limit") 40 if limitStr != "" { 41 limit, err := strconv.ParseInt(limitStr, 10, 0) 42 if err != nil { 43 return err 44 } 45 l.Limit = int(limit) 46 } 47 offsetStr := r.URL.Query().Get("offset") 48 if offsetStr != "" { 49 offset, err := strconv.ParseInt(offsetStr, 10, 0) 50 if err != nil { 51 return err 52 } 53 l.Offset = int(offset) 54 } 55 56 filterStr := r.URL.Query().Get("filter") 57 if filterStr != "" { 58 l = l.WithFilters(strings.Split(r.FormValue("filter"), ",")...) 59 } 60 61 l = l.WithOrderBy(r.URL.Query().Get("orderby")) 62 63 if l.IsEmpty() { 64 return nil 65 } 66 if !lp.IsEmpty() { 67 return ErrListParamsNotEmpty 68 } 69 70 *lp = l 71 return nil 72 } 73 74 // All returns true if List is attempting to list all available items 75 func (lp List) All() bool { 76 return lp.Limit == -1 && lp.Offset == 0 77 } 78 79 // Validate returns an error if any fields or field combinations are invalid 80 func (lp List) Validate() error { 81 if lp.Limit < 0 && lp.Limit != -1 { 82 return fmt.Errorf("limit of %d is out of bounds", lp.Limit) 83 } 84 if lp.Offset < 0 { 85 return fmt.Errorf("offset of %d is out of bounds", lp.Offset) 86 } 87 return nil 88 } 89 90 // IsEmpty determines if the List struct is empty 91 func (lp List) IsEmpty() bool { 92 return lp.Limit == 0 && 93 lp.Offset == 0 && 94 len(lp.Filter) == 0 && 95 len(lp.OrderBy) == 0 96 } 97 98 // WithOffsetLimit returns a new List struct that replaces the offset & limit 99 // fields 100 func (lp List) WithOffsetLimit(offset, limit int) List { 101 return List{ 102 Filter: lp.Filter, 103 OrderBy: lp.OrderBy, 104 Offset: offset, 105 Limit: limit, 106 } 107 } 108 109 // WithOrderBy returns a new List struct that replaces the OrderBy field 110 func (lp List) WithOrderBy(ob string) List { 111 return List{ 112 Filter: lp.Filter, 113 OrderBy: NewOrderByFromString(ob), 114 Offset: lp.Offset, 115 Limit: lp.Limit, 116 } 117 } 118 119 // WithFilters returns a new List struct that replaces the Filters field 120 func (lp List) WithFilters(f ...string) List { 121 return List{ 122 Filter: f, 123 OrderBy: lp.OrderBy, 124 Offset: lp.Offset, 125 Limit: lp.Limit, 126 } 127 }