From 901939bd96b38bcc6f4023d2c7075356153a6c8f Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Mon, 18 Sep 2023 00:51:40 +0900 Subject: [PATCH] Add support for limit and offset parameters for GET / endpoint Related #3372 --- src/server.go | 40 +++++++++++++++++++++++++++++++++++++--- src/terminal.go | 18 +++++++++--------- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/server.go b/src/server.go index 3698015..8fc605a 100644 --- a/src/server.go +++ b/src/server.go @@ -8,11 +8,23 @@ import ( "fmt" "net" "os" + "regexp" "strconv" "strings" "time" ) +var getRegex *regexp.Regexp + +func init() { + getRegex = regexp.MustCompile(`^GET /(?:\?([a-z0-9=&]+))? HTTP`) +} + +type getParams struct { + limit int + offset int +} + const ( crlf = "\r\n" httpOk = "HTTP/1.1 200 OK" + crlf @@ -117,9 +129,9 @@ func (server *httpServer) handleHttpRequest(conn net.Conn) string { text := scanner.Text() switch section { case 0: - // TODO: Parameter support e.g. "GET /?limit=100 HTTP" - if strings.HasPrefix(text, "GET / HTTP") { - server.actionChannel <- []*action{{t: actResponse}} + getMatch := getRegex.FindStringSubmatch(text) + if len(getMatch) > 0 { + server.actionChannel <- []*action{{t: actResponse, a: getMatch[1]}} response := <-server.responseChannel return good(response) } else if !strings.HasPrefix(text, "POST / HTTP") { @@ -175,3 +187,25 @@ func (server *httpServer) handleHttpRequest(conn net.Conn) string { server.actionChannel <- actions 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 +} diff --git a/src/terminal.go b/src/terminal.go index 1d8b55b..3a8c773 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -152,6 +152,7 @@ type StatusItem struct { type Status struct { Reading bool `json:"reading"` + Progress int `json:"progress"` Query string `json:"query"` Position int `json:"position"` Sort bool `json:"sort"` @@ -3022,7 +3023,7 @@ func (t *Terminal) Loop() { switch a.t { case actIgnore: case actResponse: - t.serverOutputChan <- t.dumpStatus() + t.serverOutputChan <- t.dumpStatus(parseGetParams(a.a)) case actBecome: valid, list := t.buildPlusList(a.a, false) 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() string { +func (t *Terminal) dumpStatus(params getParams) string { selectedItems := t.sortSelected() - selected := make([]StatusItem, util.Min(dumpItemLimit, len(selectedItems))) - for i, selectedItem := range selectedItems[:len(selected)] { - selected[i] = t.dumpItem(selectedItem.item) + selected := make([]StatusItem, util.Max(0, util.Min(params.limit, len(selectedItems)-params.offset))) + for i := range selected { + 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 { - matches[i] = t.dumpItem(t.merger.Get(i).item) + matches[i] = t.dumpItem(t.merger.Get(i + params.offset).item) } var current *StatusItem @@ -3825,6 +3824,7 @@ func (t *Terminal) dumpStatus() string { dump := Status{ Reading: t.reading, + Progress: t.progress, Query: string(t.input), Position: t.cy, Sort: t.sort,