From 265cf8fbe50984c3ffc0f92b3c65734addd50bd8 Mon Sep 17 00:00:00 2001 From: Thanatat Tamtan Date: Mon, 25 May 2026 11:15:21 +0700 Subject: [PATCH] fix: strip trailing slash from endpoint in Search The ingest path (built in loop) already called strings.TrimSuffix on the endpoint before appending "/ingest", but Search used c.endpoint+"/search" directly. A caller who passes an endpoint with a trailing slash would get a double-slash URL (e.g. /api/v1/index//search) that servers and proxies commonly reject with 404 or 400. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- quickwit.go | 2 +- quickwit_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/quickwit.go b/quickwit.go index c86ffb9..4eb76de 100644 --- a/quickwit.go +++ b/quickwit.go @@ -447,7 +447,7 @@ func (c *Client) Search(ctx context.Context, query string, opt *SearchOpt) (*Sea return nil, err } - req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.endpoint+"/search", bytes.NewReader(reqBody)) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, strings.TrimSuffix(c.endpoint, "/")+"/search", bytes.NewReader(reqBody)) if err != nil { return nil, err } diff --git a/quickwit_test.go b/quickwit_test.go index 99428ff..8fce6d8 100644 --- a/quickwit_test.go +++ b/quickwit_test.go @@ -2,6 +2,7 @@ package quickwit_test import ( "bytes" + "context" "encoding/json" "io" "net/http" @@ -179,3 +180,28 @@ func TestIngest_OversizeBatchPreservesOrder(t *testing.T) { } } } + +// Regression: Search did not strip a trailing slash from the endpoint before appending +// "/search", producing a double-slash URL that many servers/proxies reject. +func TestSearch_TrailingSlashEndpoint(t *testing.T) { + var capturedPath string + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + capturedPath = r.URL.Path + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"hits":[],"num_hits":0,"elapsed_time_micros":1}`)) + })) + defer server.Close() + + // Intentionally add trailing slash to endpoint + c := quickwit.NewClient(server.URL + "/api/v1/test/") + ctx := context.Background() + c.Search(ctx, "*", nil) + + if strings.Contains(capturedPath, "//") { + t.Errorf("Search URL contains double slash: %s", capturedPath) + } + if !strings.HasSuffix(capturedPath, "/search") { + t.Errorf("Search URL does not end with /search: %s", capturedPath) + } +}