From 48bdb8a37784007a84490a09a49c40e0f1e5dd58 Mon Sep 17 00:00:00 2001 From: Josh Dolitsky Date: Tue, 1 Apr 2025 12:42:05 -0500 Subject: [PATCH] Add SearchWithNext method to allow paging Signed-off-by: Josh Dolitsky --- examples/search/search.go | 16 ++++++++++++++++ request_test.go | 2 ++ search.go | 32 +++++++++++++++++++++++++++----- search_test.go | 20 ++++++++++++++++++-- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/examples/search/search.go b/examples/search/search.go index fb8c419..b9b8391 100644 --- a/examples/search/search.go +++ b/examples/search/search.go @@ -29,4 +29,20 @@ func main() { fmt.Printf("%+v\n", v) } + // search example with paging using SearchWithNext and Links.Next + next := "" + for { + resp, err := api.SearchWithNext(query, next) + if err != nil { + log.Fatal(err) + } + for _, v := range result.Results { + fmt.Printf("%+v\n", v) + } + next = resp.Links.Next + if next == "" { + break + } + log.Printf("Using next page: %s", next) + } } diff --git a/request_test.go b/request_test.go index 8060c9f..4b768f7 100644 --- a/request_test.go +++ b/request_test.go @@ -343,6 +343,8 @@ func confluenceRestAPIStub() *httptest.Server { resp = User{} case "/wiki/rest/api/search": resp = Search{} + case "/wiki/rest/api/search?next=true&cursor=abc123": + resp = Search{} case "/wiki/rest/api/content/42/history": resp = History{} case "/wiki/rest/api/content/42/label": diff --git a/search.go b/search.go index 1b48aa8..3a5f1c0 100644 --- a/search.go +++ b/search.go @@ -8,11 +8,20 @@ import ( // Search results type Search struct { - Results []Results `json:"results"` - Start int `json:"start,omitempty"` - Limit int `json:"limit,omitempty"` - Size int `json:"size,omitempty"` - TotalSize int `json:"totalSize,omitempty"` + Results []Results `json:"results"` + Start int `json:"start,omitempty"` + Limit int `json:"limit,omitempty"` + Size int `json:"size,omitempty"` + TotalSize int `json:"totalSize,omitempty"` + Links SearchLinks `json:"_links,omitempty"` +} + +// Parsing out the _links section to allow paging etc. +type SearchLinks struct { + Base string `json:"base,omitempty"` + Context string `json:"content,omitempty"` + Next string `json:"next,omitempty"` + Self string `json:"self,omitempty"` } // SearchQuery defines query parameters used for searchng @@ -41,6 +50,19 @@ func (a *API) Search(query SearchQuery) (*Search, error) { return a.SendSearchRequest(ep, "GET") } +// Search querys confluence using CQL, with the ability to pass in the Next header +// Empty Next header will run search like normal +func (a *API) SearchWithNext(query SearchQuery, next string) (*Search, error) { + if next == "" { + return a.Search(query) + } + ep, err := url.ParseRequestURI(a.endPoint.String() + strings.TrimPrefix(next, "/rest/api")) + if err != nil { + return nil, err + } + return a.SendSearchRequest(ep, "GET") +} + // addSearchQueryParams adds the defined query parameters func addSearchQueryParams(query SearchQuery) *url.Values { diff --git a/search_test.go b/search_test.go index 5fde8b7..b01f875 100644 --- a/search_test.go +++ b/search_test.go @@ -11,8 +11,8 @@ func TestSearchQueryParams(t *testing.T) { CQL: "test", CQLContext: "test", IncludeArchivedSpaces: true, - Limit: 1, - Start: 1, + Limit: 1, + Start: 1, } p := addSearchQueryParams(query) assert.Equal(t, p.Get("cql"), "test") @@ -34,3 +34,19 @@ func TestSearch(t *testing.T) { assert.Equal(t, &Search{}, s) } + +func TestSearchWithNext(t *testing.T) { + server := confluenceRestAPIStub() + defer server.Close() + + api, err := NewAPI(server.URL+"/wiki/rest/api", "userame", "token") + assert.Nil(t, err) + + s, err := api.SearchWithNext(SearchQuery{}, "") + assert.Nil(t, err) + assert.Equal(t, &Search{}, s) + + s, err = api.SearchWithNext(SearchQuery{}, "/rest/api/search?next=true&cursor=abc123") + assert.Nil(t, err) + assert.Equal(t, &Search{}, s) +}