From 93ca45570a1c663c2c80804e7ad4dae27a9bbbb6 Mon Sep 17 00:00:00 2001 From: Andrew Gillis Date: Sun, 24 Sep 2023 12:40:07 -0700 Subject: [PATCH] Return same not-found response from dh and non-dh clients (#124) The Client and DHashClient need to return the same response when no results are found. Return empty response for not found to preserve compatability with clients that expect non-nil response. Fixes #53 --- find/client/client.go | 47 +++++++++++++++++-------------------- find/client/dhash_client.go | 20 +++++++++++----- find/client/interface.go | 13 +++++++--- 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/find/client/client.go b/find/client/client.go index aa82ec2..4fe5e80 100644 --- a/find/client/client.go +++ b/find/client/client.go @@ -55,7 +55,8 @@ func New(baseURL string, options ...Option) (*Client, error) { }, nil } -// Find looks up content entries by multihash. +// Find looks up content entries by multihash. If no results are found then an +// empty response without error is returned. func (c *Client) Find(ctx context.Context, m multihash.Multihash) (*model.FindResponse, error) { u := c.findURL.JoinPath(m.B58String()) req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) @@ -63,7 +64,26 @@ func (c *Client) Find(ctx context.Context, m multihash.Multihash) (*model.FindRe return nil, err } - return c.sendRequest(req) + req.Header.Set("Content-Type", "application/json") + resp, err := c.c.Do(req) + if err != nil { + return nil, err + } + // Handle failed requests + if resp.StatusCode != http.StatusOK { + if resp.StatusCode == http.StatusNotFound { + return &model.FindResponse{}, nil + } + return nil, fmt.Errorf("find query failed: %v", http.StatusText(resp.StatusCode)) + } + + defer resp.Body.Close() + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return model.UnmarshalFindResponse(b) } func (c *Client) ListProviders(ctx context.Context) ([]*model.ProviderInfo, error) { @@ -154,26 +174,3 @@ func (c *Client) GetStats(ctx context.Context) (*model.Stats, error) { return model.UnmarshalStats(body) } - -func (c *Client) sendRequest(req *http.Request) (*model.FindResponse, error) { - req.Header.Set("Content-Type", "application/json") - resp, err := c.c.Do(req) - if err != nil { - return nil, err - } - // Handle failed requests - if resp.StatusCode != http.StatusOK { - if resp.StatusCode == http.StatusNotFound { - return &model.FindResponse{}, nil - } - return nil, fmt.Errorf("batch find query failed: %v", http.StatusText(resp.StatusCode)) - } - - defer resp.Body.Close() - b, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - return model.UnmarshalFindResponse(b) -} diff --git a/find/client/dhash_client.go b/find/client/dhash_client.go index f465e61..4f1aac4 100644 --- a/find/client/dhash_client.go +++ b/find/client/dhash_client.go @@ -98,7 +98,8 @@ func (c *DHashClient) PCache() *pcache.ProviderCache { } // Find launches FindAsync in a separate go routine and assembles the result -// into FindResponse as if it was a synchronous invocation. +// into FindResponse as if it was a synchronous invocation. If no results are +// found then an empty response without error is returned. func (c *DHashClient) Find(ctx context.Context, mh multihash.Multihash) (*model.FindResponse, error) { resChan := make(chan model.ProviderResult) errChan := make(chan error, 1) @@ -107,18 +108,25 @@ func (c *DHashClient) Find(ctx context.Context, mh multihash.Multihash) (*model. errChan <- c.FindAsync(ctx, mh, resChan) }() - mhr := model.MultihashResult{ - Multihash: mh, - } + var providerResults []model.ProviderResult for pr := range resChan { - mhr.ProviderResults = append(mhr.ProviderResults, pr) + providerResults = append(providerResults, pr) } err := <-errChan if err != nil { return nil, err } + if len(providerResults) == 0 { + return &model.FindResponse{}, nil + } + return &model.FindResponse{ - MultihashResults: []model.MultihashResult{mhr}, + MultihashResults: []model.MultihashResult{ + { + Multihash: mh, + ProviderResults: providerResults, + }, + }, }, nil } diff --git a/find/client/interface.go b/find/client/interface.go index c93a65e..dbbaf2d 100644 --- a/find/client/interface.go +++ b/find/client/interface.go @@ -12,14 +12,14 @@ import ( // Finder is the interface implemented by all find clients. type Finder interface { - // Find queries for provider content records for a single multihash. + // Find queries for provider content records for a single multihash. If no + // results are found then an empty response without error is returned. Find(context.Context, multihash.Multihash) (*model.FindResponse, error) } // FindBatch is a convenience function to lookup results for multiple // multihashes. This works with either the Client or DHashClient. If no results -// are found, then an error is not returned and there are no results in the -// response. +// are found then an empty response without error is returned. func FindBatch(ctx context.Context, finder Finder, mhs []multihash.Multihash) (*model.FindResponse, error) { var resp *model.FindResponse for i := range mhs { @@ -31,11 +31,18 @@ func FindBatch(ctx context.Context, finder Finder, mhs []multihash.Multihash) (* } return nil, err } + if r == nil || len(r.MultihashResults) == 0 { + // multihash not found + continue + } if resp == nil { resp = r } else { resp.MultihashResults = append(resp.MultihashResults, r.MultihashResults...) } } + if resp == nil { + resp = &model.FindResponse{} + } return resp, nil }