Skip to content

Commit

Permalink
Add backoff to List
Browse files Browse the repository at this point in the history
  • Loading branch information
charlieegan3 committed Sep 8, 2021
1 parent 77837ce commit f1bc567
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 14 deletions.
47 changes: 47 additions & 0 deletions pkg/carddav/backoff_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package carddav

import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"

"github.com/maxatome/go-testdeep/td"
)

func TestBackoff(t *testing.T) {
requestCount := 0
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestCount++
if requestCount < 2 {
w.WriteHeader(http.StatusInternalServerError)
return
}

td.Cmp(t, r.Method, "PROPFIND")
td.Cmp(t, r.Header["Authorization"], []string{"Basic YWxpY2U6cGFzc3dvcmQ="})
td.Cmp(t, r.Header["Depth"], []string{"1"})

b, err := ioutil.ReadFile("propfind.xml")
td.Cmp(t, err, nil)
w.Write(b)
}))

expectedItems := []string{
"6316e64d-176c-42bc-9d59-30ed53c1a06b",
"a5fadfc4-27fc-459c-847d-c8dabe3f789e",
}

cardDavClient := Client{
URL: testServer.URL + "/dav/addressbooks/user/charlieegan3@fastmail.com/Default",
User: "alice",
Password: "password",
}

gotItems, err := cardDavClient.List()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

td.Cmp(t, gotItems, expectedItems)
}
47 changes: 33 additions & 14 deletions pkg/carddav/client.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package carddav

import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"

"github.com/antchfx/xmlquery"
"github.com/cenkalti/backoff/v4"
"github.com/pkg/errors"
)

Expand All @@ -18,28 +21,44 @@ type Client struct {
}

func (c *Client) List() (items []string, err error) {
req, err := http.NewRequest("PROPFIND", c.URL, nil)
if err != nil {
return items, errors.Wrap(err, "failed to make PROPFIND request to list items in carddav endpoint")
}
req.SetBasicAuth(c.User, c.Password)
req.Header.Add("Depth", "1")
var body []byte
operation := func() error {
req, err := http.NewRequest("PROPFIND", c.URL, nil)
if err != nil {
return errors.Wrap(err, "failed to make PROPFIND request to list items in carddav endpoint")
}
req.SetBasicAuth(c.User, c.Password)
req.Header.Add("Depth", "1")

resp, err := http.DefaultClient.Do(req)
if err != nil {
return items, errors.Wrap(err, "failed to make request")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return errors.Wrap(err, "failed to make request")
}
defer resp.Body.Close()

if resp.StatusCode > 399 || resp.StatusCode < 100 {
return fmt.Errorf("server returned error: %d", resp.StatusCode)
}

body, err = io.ReadAll(resp.Body)
if err != nil {
return errors.Wrap(err, "failed to read request body")
}

return nil
}
defer resp.Body.Close()

if resp.StatusCode > 399 || resp.StatusCode < 100 {
return items, errors.Wrap(err, "server returned error: ")
b := backoff.NewExponentialBackOff()

err = backoff.Retry(operation, b)
if err != nil {
return items, errors.Wrap(err, "failed to list carddav items after backoff")
}

doc, err := xmlquery.Parse(resp.Body)
doc, err := xmlquery.Parse(bytes.NewReader(body))
if err != nil {
return items, errors.Wrap(err, "failed parse body as xml")
}

list, err := xmlquery.QueryAll(doc, "D:multistatus/D:response/D:href")
if err != nil {
return items, errors.Wrap(err, "failed to query body for hrefs")
Expand Down

0 comments on commit f1bc567

Please sign in to comment.