Add support for limit and offset parameters for GET / endpoint

Related #3372
This commit is contained in:
Junegunn Choi 2023-09-18 00:51:40 +09:00
parent edfdcc8cee
commit 901939bd96
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
2 changed files with 46 additions and 12 deletions

View File

@ -8,11 +8,23 @@ import (
"fmt" "fmt"
"net" "net"
"os" "os"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
) )
var getRegex *regexp.Regexp
func init() {
getRegex = regexp.MustCompile(`^GET /(?:\?([a-z0-9=&]+))? HTTP`)
}
type getParams struct {
limit int
offset int
}
const ( const (
crlf = "\r\n" crlf = "\r\n"
httpOk = "HTTP/1.1 200 OK" + crlf httpOk = "HTTP/1.1 200 OK" + crlf
@ -117,9 +129,9 @@ func (server *httpServer) handleHttpRequest(conn net.Conn) string {
text := scanner.Text() text := scanner.Text()
switch section { switch section {
case 0: case 0:
// TODO: Parameter support e.g. "GET /?limit=100 HTTP" getMatch := getRegex.FindStringSubmatch(text)
if strings.HasPrefix(text, "GET / HTTP") { if len(getMatch) > 0 {
server.actionChannel <- []*action{{t: actResponse}} server.actionChannel <- []*action{{t: actResponse, a: getMatch[1]}}
response := <-server.responseChannel response := <-server.responseChannel
return good(response) return good(response)
} else if !strings.HasPrefix(text, "POST / HTTP") { } else if !strings.HasPrefix(text, "POST / HTTP") {
@ -175,3 +187,25 @@ func (server *httpServer) handleHttpRequest(conn net.Conn) string {
server.actionChannel <- actions server.actionChannel <- actions
return httpOk return httpOk
} }
func parseGetParams(query string) getParams {
params := getParams{limit: 100, offset: 0}
for _, pair := range strings.Split(query, "&") {
parts := strings.SplitN(pair, "=", 2)
if len(parts) == 2 {
switch parts[0] {
case "limit":
val, err := strconv.Atoi(parts[1])
if err == nil {
params.limit = val
}
case "offset":
val, err := strconv.Atoi(parts[1])
if err == nil {
params.offset = val
}
}
}
}
return params
}

View File

@ -152,6 +152,7 @@ type StatusItem struct {
type Status struct { type Status struct {
Reading bool `json:"reading"` Reading bool `json:"reading"`
Progress int `json:"progress"`
Query string `json:"query"` Query string `json:"query"`
Position int `json:"position"` Position int `json:"position"`
Sort bool `json:"sort"` Sort bool `json:"sort"`
@ -3022,7 +3023,7 @@ func (t *Terminal) Loop() {
switch a.t { switch a.t {
case actIgnore: case actIgnore:
case actResponse: case actResponse:
t.serverOutputChan <- t.dumpStatus() t.serverOutputChan <- t.dumpStatus(parseGetParams(a.a))
case actBecome: case actBecome:
valid, list := t.buildPlusList(a.a, false) valid, list := t.buildPlusList(a.a, false)
if valid { if valid {
@ -3802,18 +3803,16 @@ func (t *Terminal) dumpItem(i *Item) StatusItem {
} }
} }
const dumpItemLimit = 100 // TODO: Make configurable via GET parameter func (t *Terminal) dumpStatus(params getParams) string {
func (t *Terminal) dumpStatus() string {
selectedItems := t.sortSelected() selectedItems := t.sortSelected()
selected := make([]StatusItem, util.Min(dumpItemLimit, len(selectedItems))) selected := make([]StatusItem, util.Max(0, util.Min(params.limit, len(selectedItems)-params.offset)))
for i, selectedItem := range selectedItems[:len(selected)] { for i := range selected {
selected[i] = t.dumpItem(selectedItem.item) selected[i] = t.dumpItem(selectedItems[i+params.offset].item)
} }
matches := make([]StatusItem, util.Min(dumpItemLimit, t.merger.Length())) matches := make([]StatusItem, util.Max(0, util.Min(params.limit, t.merger.Length()-params.offset)))
for i := range matches { for i := range matches {
matches[i] = t.dumpItem(t.merger.Get(i).item) matches[i] = t.dumpItem(t.merger.Get(i + params.offset).item)
} }
var current *StatusItem var current *StatusItem
@ -3825,6 +3824,7 @@ func (t *Terminal) dumpStatus() string {
dump := Status{ dump := Status{
Reading: t.reading, Reading: t.reading,
Progress: t.progress,
Query: string(t.input), Query: string(t.input),
Position: t.cy, Position: t.cy,
Sort: t.sort, Sort: t.sort,