fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

Fix /api/search endpoint encoding error (#506)

Previously this endpoint was always returning an empty response for
valid requests. This is because the last line failed to encode the
SearchResult as JSON. After some investigation I can see that this is
because we default the Progress fields to `-Inf`. Since these progress
fields only seemm to be applicable for streaming use cases that use RPC
and don't encode as JSON then it seemed like the best fix was to simply
omit them in the JSON response.

This change also adds error handling to the JSON encoding so that these
errors will be simpler to debug in future. A test is also included that
reproduces the issue.

You can reproduce this issue and the fix locally by just curling the
search endpoint like:

```bash
curl -H 'Accept: application/json' -XPOST -d '{"Q":"a.*"}' 'http://127.0.0.1:6070/api/search' -i
```

author
Dylan
committer
GitHub
date (Jan 24, 2023, 8:21 AM +0200) commit f4df5468 parent 5f79575b
+43 -2
+4 -1
api.go
··· 479 479 // SearchResult contains search matches and extra data 480 480 type SearchResult struct { 481 481 Stats 482 - Progress 482 + 483 + // Do not encode this as we cannot encode -Inf in JSON 484 + Progress `json:"-"` 485 + 483 486 Files []FileMatch 484 487 485 488 // RepoURLs holds a repo => template string map.
+6 -1
json/json.go
··· 91 91 return 92 92 } 93 93 94 - json.NewEncoder(w).Encode(jsonSearchReply{searchResult}) 94 + err = json.NewEncoder(w).Encode(jsonSearchReply{searchResult}) 95 + 96 + if err != nil { 97 + jsonError(w, http.StatusInternalServerError, err.Error()) 98 + return 99 + } 95 100 } 96 101 97 102 func jsonError(w http.ResponseWriter, statusCode int, err string) {
+33
json/json_test.go
··· 4 4 "bytes" 5 5 "encoding/json" 6 6 "io" 7 + "math" 7 8 "net/http" 8 9 "net/http/httptest" 9 10 "reflect" ··· 83 84 } 84 85 if !reflect.DeepEqual(listResult.List, mock.RepoList) { 85 86 t.Fatalf("got %+v, want %+v", listResult, mock.RepoList) 87 + } 88 + } 89 + 90 + func TestProgressNotEncodedInSearch(t *testing.T) { 91 + searchQuery := "hello" 92 + mock := &mockSearcher.MockSearcher{ 93 + WantSearch: mustParse(searchQuery), 94 + SearchResult: &zoekt.SearchResult{ 95 + // Validate that Progress is ignored as we cannot encode -Inf 96 + Progress: zoekt.Progress{ 97 + Priority: math.Inf(-1), 98 + MaxPendingPriority: math.Inf(-1), 99 + }, 100 + Files: []zoekt.FileMatch{}, 101 + }, 102 + } 103 + 104 + ts := httptest.NewServer(zjson.JSONServer(mock)) 105 + defer ts.Close() 106 + 107 + searchBody, err := json.Marshal(struct{ Q string }{Q: searchQuery}) 108 + if err != nil { 109 + t.Fatal(err) 110 + } 111 + r, err := http.Post(ts.URL+"/search", "application/json", bytes.NewBuffer(searchBody)) 112 + if err != nil { 113 + t.Fatal(err) 114 + } 115 + 116 + if r.StatusCode != 200 { 117 + body, _ := io.ReadAll(r.Body) 118 + t.Fatalf("Got status code %d, err %s", r.StatusCode, string(body)) 86 119 } 87 120 } 88 121