hivedav

A curlable free/busy scheduler with CalDAV integration
git clone https://git.in0rdr.ch/hivedav.git
Log | Files | Refs | Pull requests | README | LICENSE

commit 81da8f24b9a8cd4e300750a834690aeb8c4ede5d
parent 0e797f86b169a64cb13b2ccef50c777aef6a6c79
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date:   Sun, 16 Jun 2024 14:37:03 +0200

fix(http): close body and follow redirect

Diffstat:
Mcaldav/caldav.go | 27++++++++++++++++++++++++++-
Mdocs/CALDAV.md | 12+++++-------
2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/caldav/caldav.go b/caldav/caldav.go @@ -51,10 +51,32 @@ func UserPrincipal(caldavHost string, user string, pass string) (string, error) req.Header.Set("Content-Type", "text/xml") req.SetBasicAuth(user, pass) - res, err := http.DefaultClient.Do(req) + client := &http.Client{ + CheckRedirect: func(req *http.Request, via []*http.Request) error { + // return real redirect response code (>=300) + return http.ErrUseLastResponse + }, + } + res, err := client.Do(req) if err != nil { return "", err } + defer res.Body.Close() + + redirectUri, err := res.Location() + + if res.StatusCode >= 300 && res.StatusCode <= 399 { + // follow first redirect to suggested uri, repeat request + // some providers are not discoverable starting at caldavHost + req, err = http.NewRequest("PROPFIND", caldavHost+redirectUri.Path, reader) + req.Header.Set("Depth", "0") + req.Header.Set("Content-Type", "text/xml") + req.SetBasicAuth(user, pass) + res, err = client.Do(req) + if err != nil { + return "", err + } + } if res.StatusCode != 207 { return "", err @@ -88,6 +110,7 @@ func CalendarHome(caldavHost string, user string, pass string, userPrincipal str req.SetBasicAuth(user, pass) res, err := http.DefaultClient.Do(req) + defer res.Body.Close() if err != nil { return "", err } @@ -127,6 +150,7 @@ func CalendarFromHomeSet(caldavHost string, user string, pass string, homeSetPat req.SetBasicAuth(user, pass) res, err := http.DefaultClient.Do(req) + defer res.Body.Close() if err != nil { return "", err } @@ -181,6 +205,7 @@ func GetAvailabilityByUrl(calendarUrl string, user string, pass string) (data [] req.SetBasicAuth(user, pass) res, err := http.DefaultClient.Do(req) + defer res.Body.Close() if err != nil { return data, err } diff --git a/docs/CALDAV.md b/docs/CALDAV.md @@ -11,14 +11,12 @@ To debug the flow, use the xml snippets from the code and curl. ## Tested providers * GMX - - discovery with `HIVEDAV_CALDAV_HOST` does not work, use direct link to - calendar uri (`HIVEDAV_CALDAV_URI`) - - example: + - example 1: `HIVEDAV_CALDAV_HOST=https://caldav.gmx.net` and + `HIVEDAV_CALENDAR=1` + - example 2: `HIVEDAV_CALDAV_URI=https://caldav.gmx.net/begenda/dav/$PRINCIPAL/calendar` - https://hilfe.gmx.net/kalender/mobil/apps.html * Yahoo - - works with `HIVEDAV_CALDAV_HOST` automatic discovery or direct calendar uri - using `HIVEDAV_CALDAV_URI` - create app password for `HIVEDAV_CALDAV_PASSWORD` at https://login.yahoo.com/myaccount/security/app-password - example 1: `HIVEDAV_CALDAV_HOST=https://caldav.calendar.yahoo.com` and @@ -41,7 +39,7 @@ with any provider. First, read the principal: ``` cat <<EOF | curl -s -d @- -XPROPFIND -H "Content-Type: text/xml" -H "Depth: 0" \ - -u '$USER:$PASSWORD' $CALDAV_HOST | xmllint --format - + -u '$USER:$PASSWORD' -L $CALDAV_HOST | xmllint --format - <d:propfind xmlns:d="DAV:"> <d:prop> <d:current-user-principal /> @@ -51,7 +49,7 @@ EOF ``` The principal path (`$PRINCIPAL`) is returned in the XML response tag `<DAV:current-user-principal>`. For some providers, `$CALDAV_HOST` has a -special prefix (such as `/begenda/dav/users` for GMX, read the 302 redirect +special prefix (such as `/begenda/dav/users` for GMX, follow the 302 redirect location with curl). Get calendar home set for the principal: