Browse Source

client: add KeysAPI.Delete

Brian Waldon 11 years ago
parent
commit
0f31f403d1
2 changed files with 129 additions and 0 deletions
  1. 43 0
      client/keys.go
  2. 86 0
      client/keys_test.go

+ 43 - 0
client/keys.go

@@ -65,6 +65,8 @@ type KeysAPI interface {
 	Create(ctx context.Context, key, value string) (*Response, error)
 	Update(ctx context.Context, key, value string) (*Response, error)
 
+	Delete(ctx context.Context, key string, opts DeleteOptions) (*Response, error)
+
 	Get(ctx context.Context, key string) (*Response, error)
 	RGet(ctx context.Context, key string) (*Response, error)
 
@@ -76,6 +78,10 @@ type SetOptions struct {
 	PrevExist PrevExistType
 }
 
+type DeleteOptions struct {
+	Recursive bool
+}
+
 type Watcher interface {
 	Next(context.Context) (*Response, error)
 }
@@ -129,6 +135,21 @@ func (k *httpKeysAPI) Update(ctx context.Context, key, val string) (*Response, e
 	return k.Set(ctx, key, val, SetOptions{PrevExist: PrevExist})
 }
 
+func (k *httpKeysAPI) Delete(ctx context.Context, key string, opts DeleteOptions) (*Response, error) {
+	act := &deleteAction{
+		Prefix:  k.prefix,
+		Key:     key,
+		Options: opts,
+	}
+
+	resp, body, err := k.client.Do(ctx, act)
+	if err != nil {
+		return nil, err
+	}
+
+	return unmarshalHTTPResponse(resp.StatusCode, resp.Header, body)
+}
+
 func (k *httpKeysAPI) Get(ctx context.Context, key string) (*Response, error) {
 	get := &getAction{
 		Prefix:    k.prefix,
@@ -276,6 +297,28 @@ func (a *setAction) HTTPRequest(ep url.URL) *http.Request {
 	return req
 }
 
+type deleteAction struct {
+	Prefix  string
+	Key     string
+	Value   string
+	Options DeleteOptions
+}
+
+func (a *deleteAction) HTTPRequest(ep url.URL) *http.Request {
+	u := v2KeysURL(ep, a.Prefix, a.Key)
+
+	params := u.Query()
+	if a.Options.Recursive {
+		params.Set("recursive", "true")
+	}
+	u.RawQuery = params.Encode()
+
+	req, _ := http.NewRequest("DELETE", u.String(), nil)
+	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+
+	return req
+}
+
 func unmarshalHTTPResponse(code int, header http.Header, body []byte) (res *Response, err error) {
 	switch code {
 	case http.StatusOK, http.StatusCreated:

+ 86 - 0
client/keys_test.go

@@ -304,6 +304,92 @@ func TestSetAction(t *testing.T) {
 	}
 }
 
+func TestDeleteAction(t *testing.T) {
+	wantHeader := http.Header(map[string][]string{
+		"Content-Type": []string{"application/x-www-form-urlencoded"},
+	})
+
+	tests := []struct {
+		act     deleteAction
+		wantURL string
+	}{
+		// default prefix
+		{
+			act: deleteAction{
+				Prefix: DefaultV2KeysPrefix,
+				Key:    "foo",
+			},
+			wantURL: "http://example.com/v2/keys/foo",
+		},
+
+		// non-default prefix
+		{
+			act: deleteAction{
+				Prefix: "/pfx",
+				Key:    "foo",
+			},
+			wantURL: "http://example.com/pfx/foo",
+		},
+
+		// no prefix
+		{
+			act: deleteAction{
+				Key: "foo",
+			},
+			wantURL: "http://example.com/foo",
+		},
+
+		// Key with path separators
+		{
+			act: deleteAction{
+				Prefix: DefaultV2KeysPrefix,
+				Key:    "foo/bar/baz",
+			},
+			wantURL: "http://example.com/v2/keys/foo/bar/baz",
+		},
+
+		// Key with leading slash, Prefix with trailing slash
+		{
+			act: deleteAction{
+				Prefix: "/foo/",
+				Key:    "/bar",
+			},
+			wantURL: "http://example.com/foo/bar",
+		},
+
+		// Key with trailing slash
+		{
+			act: deleteAction{
+				Key: "/foo/",
+			},
+			wantURL: "http://example.com/foo",
+		},
+
+		// Recursive set to true
+		{
+			act: deleteAction{
+				Key: "foo",
+				Options: DeleteOptions{
+					Recursive: true,
+				},
+			},
+			wantURL: "http://example.com/foo?recursive=true",
+		},
+	}
+
+	for i, tt := range tests {
+		u, err := url.Parse(tt.wantURL)
+		if err != nil {
+			t.Errorf("#%d: unable to use wantURL fixture: %v", i, err)
+		}
+
+		got := tt.act.HTTPRequest(url.URL{Scheme: "http", Host: "example.com"})
+		if err := assertRequest(*got, "DELETE", u, wantHeader, nil); err != nil {
+			t.Errorf("#%d: %v", i, err)
+		}
+	}
+}
+
 func assertRequest(got http.Request, wantMethod string, wantURL *url.URL, wantHeader http.Header, wantBody []byte) error {
 	if wantMethod != got.Method {
 		return fmt.Errorf("want.Method=%#v got.Method=%#v", wantMethod, got.Method)