From e7f6db64461970fd8c7ae48ef68b775f5c48c679 Mon Sep 17 00:00:00 2001 From: lancecarlson Date: Wed, 16 Jan 2013 16:24:25 -0500 Subject: [PATCH 1/3] More robust response handling for BulkSave and Copy --- couch.go | 66 +++++++++++++++++++++++++++++---------------------- couch_test.go | 4 ++-- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/couch.go b/couch.go index 6f4b607..8f33c3a 100644 --- a/couch.go +++ b/couch.go @@ -120,7 +120,7 @@ type BulkSaveRequest struct { Docs []map[string]interface{} `json:"docs"` } -func (c *Client) BulkSave(docs ...interface{}) (resp *http.Response, err error) { +func (c *Client) BulkSave(docs ...interface{}) (resp *[]Response, code int, err error) { sliceDocs, err := StripIdRevSlice(docs) bulkSaveRequest := &BulkSaveRequest{Docs: sliceDocs} reader, err := docReader(bulkSaveRequest) @@ -129,7 +129,11 @@ func (c *Client) BulkSave(docs ...interface{}) (resp *http.Response, err error) if err != nil { return } - resp, err = http.DefaultClient.Do(req) + httpResp, err := http.DefaultClient.Do(req) + if err != nil { + return + } + code, err = c.HandleResponse(httpResp, &resp) if err != nil { return } @@ -161,7 +165,7 @@ func (c *Client) ViewRaw(design string, name string, options *url.Values) (*Mult return multiDocResponse, nil } -func (c *Client) Copy(src string, dest string, destRev *string) (resp *http.Response, err error) { +func (c *Client) Copy(src string, dest string, destRev *string) (resp *Response, code int, err error) { if destRev != nil { dest += "?rev=" + *destRev } @@ -171,7 +175,11 @@ func (c *Client) Copy(src string, dest string, destRev *string) (resp *http.Resp if err != nil { return } - resp, err = http.DefaultClient.Do(req) + httpResp, err := http.DefaultClient.Do(req) + if err != nil { + return + } + code, err = c.HandleResponse(httpResp, &resp) if err != nil { return } @@ -196,7 +204,31 @@ func (c *Client) NewRequest(method, url string, body io.Reader, headers *http.He return } -func (c *Client) handleResponseError(code int, resBytes []byte) error { +func (c *Client) UrlString(path string, values *url.Values) string { + u := *c.URL + u.Path = path + if values != nil { + u.RawQuery = values.Encode() + } + return u.String() +} + +func (c *Client) HandleResponse(resp *http.Response, result interface{}) (code int, err error) { + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return + } + code = resp.StatusCode + if err = c.HandleResponseError(code, body); err != nil { + return code, err + } + if err = json.Unmarshal(body, result); err != nil { + return 0, err + } + return +} + +func (c *Client) HandleResponseError(code int, resBytes []byte) error { if code < 200 || code >= 300 { res := Response{} if err := json.Unmarshal(resBytes, &res); err != nil { @@ -207,21 +239,12 @@ func (c *Client) handleResponseError(code int, resBytes []byte) error { return nil } -func (c *Client) UrlString(path string, values *url.Values) string { - u := *c.URL - u.Path = path - if values != nil { - u.RawQuery = values.Encode() - } - return u.String() -} - func (c *Client) execJSON(method string, path string, result interface{}, doc interface{}, values *url.Values, headers *http.Header) (int, error) { resBytes, code, err := c.execRead(method, path, doc, values, headers) if err != nil { return 0, err } - if err = c.handleResponseError(code, resBytes); err != nil { + if err = c.HandleResponseError(code, resBytes); err != nil { return code, err } if err = json.Unmarshal(resBytes, result); err != nil { @@ -323,19 +346,6 @@ func StripIdRevSlice(docs interface{}) (sliceDoc []map[string]interface{}, err e } return } -/*func StripIdRev(doc interface{}) (docJson []byte, id, rev string, err error) { - idRev := &IdRev{} - err := json.Unmarshal(docJson, &idRev) - if err != nil { - return - } - if _, ok := mapDoc["_rev"]; ok { - rev = idRev.Rev - delete(mapDoc, "_rev") - } - docJson, err := json.Marhsal(mapDoc) -}*/ - func ParseIdRev(doc interface{}) (string, string, error) { docJson, err := json.Marshal(doc) if err != nil { diff --git a/couch_test.go b/couch_test.go index 8367582..3ad96e7 100644 --- a/couch_test.go +++ b/couch_test.go @@ -127,7 +127,7 @@ func TestBulkSave(t *testing.T) { cats := []interface{}{} cats = append(cats, cat1, cat2) - resp, err := c.BulkSave(cats...) + resp, _, err := c.BulkSave(cats...) if err != nil { t.Error(err) } @@ -166,7 +166,7 @@ func TestViewRaw(t *testing.T) { func TestCopy(t *testing.T) { c, _ := NewClientURL(DB) - res, err := c.Copy("explicit", "explicit-copy", nil) + res, _, err := c.Copy("explicit", "explicit-copy", nil) if err != nil { t.Error(err) } From c01a67e54a07fb93d38715df2ffd0bf3352660ff Mon Sep 17 00:00:00 2001 From: lancecarlson Date: Wed, 16 Jan 2013 16:54:29 -0500 Subject: [PATCH 2/3] Save uses Response instead of returning id and rev --- README.md | 8 ++++---- couch.go | 14 ++++++-------- couch_test.go | 25 +++++++++++-------------- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 95e0173..f971c56 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ type Cat struct { cat := Cat{Name: "Octo", Cool: true} -id, rev, err := lc.Save(cat) +resp, err := lc.Save(cat) if err != nil { // Do whatever @@ -28,14 +28,14 @@ if err != nil { lazyCat := Cat{} -err := lc.Get(id, lazyCat) +err := lc.Get(res.ID, lazyCat) fmt.Println(lazyCat) -lc.Delete(id, rev) +lc.Delete(res.ID, res.Rev) params := url.Values{"limit": []string{"5"}} -results, err := c.View("myapp", "all", ¶ms) +results, err := c.ViewRaw("myapp", "all", ¶ms) if err != nil { // Do whatever } diff --git a/couch.go b/couch.go index 8f33c3a..f16e025 100644 --- a/couch.go +++ b/couch.go @@ -65,20 +65,18 @@ func (c *Client) DeleteDB(name string) (map[string] interface{}, error) { return res, nil } -func (c *Client) Save(doc interface{}) (string, string, error) { +func (c *Client) Save(doc interface{}) (res *Response, err error) { id, _, err := ParseIdRev(doc) if err != nil { - return "", "", err + return } // Warning - this converts doc into a map[string]interface{} doc, err = StripIdRev(doc) if err != nil { - return "", "", nil + return } - res := Response{} - // If no id is provided, we assume POST if id == "" { _, err = c.execJSON("POST", c.URL.Path, &res, doc, nil, nil) @@ -87,14 +85,14 @@ func (c *Client) Save(doc interface{}) (string, string, error) { } if err != nil { - return "", "", err + return } if res.Error != "" { - return "", "", fmt.Errorf(fmt.Sprintf("%s: %s", res.Error, res.Reason)) + return res, fmt.Errorf(fmt.Sprintf("%s: %s", res.Error, res.Reason)) } - return res.ID, res.Rev, nil + return } func (c *Client) Get(id string, doc interface{}) error { diff --git a/couch_test.go b/couch_test.go index 3ad96e7..c427a80 100644 --- a/couch_test.go +++ b/couch_test.go @@ -47,19 +47,12 @@ func TestCreateAndDeleteDB(t *testing.T) { func TestSave(t *testing.T) { c, _ := NewClientURL(DB) - id, rev, err := c.Save(map[string]string{"test1": "value1", "test2": "value2"}) + res, err := c.Save(map[string]string{"test1": "value1", "test2": "value2"}) if err != nil { t.Error(err) } - - if id == "" { - t.Error(err) - } - - if rev == "" { - t.Error(err) - } - + fmt.Println("Save") + fmt.Println(res) } type Cow struct { @@ -75,10 +68,12 @@ func TestSaveWithId(t *testing.T) { c.Get("testcow", cow) c.Delete("testcow", cow.Rev) fmt.Println(cow) - _, _, err := c.Save(Cow{ID: "testcow", Name: "Fred"}) + res, err := c.Save(Cow{ID: "testcow", Name: "Fred"}) if err != nil { t.Error(err) } + fmt.Println("SaveWithId") + fmt.Println(res) } func TestGetAndSave(t *testing.T) { @@ -92,21 +87,23 @@ func TestGetAndSave(t *testing.T) { doc["updatekey"] = "updated" - _, _, err = c.Save(doc) + res, err := c.Save(doc) if err != nil { t.Error(err) } + fmt.Println("GetAndSave") + fmt.Println(res) } func TestDelete(t *testing.T) { c, _ := NewClientURL(DB) doc := map[string]string{"_id": "deleteme"} - id, rev, err := c.Save(doc) + res, err := c.Save(doc) if err != nil { t.Error(err) } - err = c.Delete(id, rev) + err = c.Delete(res.ID, res.Rev) if err != nil { t.Error(err) } From 130ee80b4ee1e684abe0470a3cab1e2d0ae74fcb Mon Sep 17 00:00:00 2001 From: lancecarlson Date: Wed, 16 Jan 2013 16:55:05 -0500 Subject: [PATCH 3/3] Typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f971c56..34ef873 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ type Cat struct { cat := Cat{Name: "Octo", Cool: true} -resp, err := lc.Save(cat) +res, err := lc.Save(cat) if err != nil { // Do whatever