From 45b7c9a4ac4e64304cdfa94e1a44f342e7faef46 Mon Sep 17 00:00:00 2001 From: Jonathan Boulle Date: Tue, 4 Nov 2014 12:51:43 -0800 Subject: [PATCH] client: return ErrNoEndpoint when none available In certain cases (for example, if a cluster peer is accessible but it has no members listed), the httpClusterClient could have an empty set of endpoints as a result of the Sync. This means that its Do function could potentially return a nil response and nil error, with catastrophic consequences for callers. To be safe (particularly about this latter behaviour), this change errors in both Sync and Do if no endpoints are available. --- client/http.go | 7 +++++++ client/http_test.go | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/client/http.go b/client/http.go index b6ab415e1..7dfecc8c2 100644 --- a/client/http.go +++ b/client/http.go @@ -30,6 +30,7 @@ import ( var ( ErrTimeout = context.DeadlineExceeded ErrCanceled = context.Canceled + ErrNoEndpoints = errors.New("no endpoints available") ErrTooManyRedirects = errors.New("too many redirects") DefaultRequestTimeout = 5 * time.Second @@ -91,6 +92,9 @@ type httpClusterClient struct { } func (c *httpClusterClient) Do(ctx context.Context, act HTTPAction) (resp *http.Response, body []byte, err error) { + if len(c.endpoints) == 0 { + return nil, nil, ErrNoEndpoints + } for _, hc := range c.endpoints { resp, body, err = hc.Do(ctx, act) if err != nil { @@ -118,6 +122,9 @@ func (c *httpClusterClient) Sync(ctx context.Context) error { for _, m := range ms { eps = append(eps, m.ClientURLs...) } + if len(eps) == 0 { + return ErrNoEndpoints + } nc, err := newHTTPClusterClient(c.transport, eps) if err != nil { return err diff --git a/client/http_test.go b/client/http_test.go index 7a8beedb1..c3cc1c9d5 100644 --- a/client/http_test.go +++ b/client/http_test.go @@ -234,6 +234,14 @@ func TestHTTPClusterClientDo(t *testing.T) { wantErr: ErrCanceled, }, + // return err if there are no endpoints + { + client: &httpClusterClient{ + endpoints: []HTTPClient{}, + }, + wantErr: ErrNoEndpoints, + }, + // return err if all endpoints return arbitrary errors { client: &httpClusterClient{