From 3a3887b358a5eaf73440dfd9f4732b356f022bf0 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 11 Feb 2020 19:14:05 +0100 Subject: [PATCH] plugins/carddav: cache addressbook home set path --- plugins/carddav/carddav.go | 26 ++------------------- plugins/carddav/plugin.go | 48 +++++++++++++++++++++++++++++++++++--- plugins/carddav/routes.go | 7 +++--- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/plugins/carddav/carddav.go b/plugins/carddav/carddav.go index 55c76b4..0c1a06d 100644 --- a/plugins/carddav/carddav.go +++ b/plugins/carddav/carddav.go @@ -21,32 +21,10 @@ func (rt *authRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) return rt.upstream.RoundTrip(req) } -func getAddressBook(u *url.URL, session *koushin.Session) (*carddav.Client, *carddav.AddressBook, error) { +func newClient(u *url.URL, session *koushin.Session) (*carddav.Client, error) { rt := authRoundTripper{ upstream: http.DefaultTransport, session: session, } - c, err := carddav.NewClient(&http.Client{Transport: &rt}, u.String()) - if err != nil { - return nil, nil, fmt.Errorf("failed to create CardDAV client: %v", err) - } - - principal, err := c.FindCurrentUserPrincipal() - if err != nil { - return nil, nil, fmt.Errorf("failed to query CardDAV principal: %v", err) - } - - addressBookHomeSet, err := c.FindAddressBookHomeSet(principal) - if err != nil { - return nil, nil, fmt.Errorf("failed to query CardDAV address book home set: %v", err) - } - - addressBooks, err := c.FindAddressBooks(addressBookHomeSet) - if err != nil { - return nil, nil, fmt.Errorf("failed to query CardDAV address books: %v", err) - } - if len(addressBooks) == 0 { - return nil, nil, errNoAddressBook - } - return c, &addressBooks[0], nil + return carddav.NewClient(&http.Client{Transport: &rt}, u.String()) } diff --git a/plugins/carddav/plugin.go b/plugins/carddav/plugin.go index 99e5f62..a77762b 100644 --- a/plugins/carddav/plugin.go +++ b/plugins/carddav/plugin.go @@ -30,6 +30,44 @@ func sanityCheckURL(u *url.URL) error { return nil } +type plugin struct { + koushin.GoPlugin + url *url.URL + homeSetCache map[string]string +} + +func (p *plugin) clientWithAddressBook(session *koushin.Session) (*carddav.Client, *carddav.AddressBook, error) { + c, err := newClient(p.url, session) + if err != nil { + return nil, nil, fmt.Errorf("failed to create CardDAV client: %v", err) + } + + homeSet, ok := p.homeSetCache[session.Username()] + if !ok { + principal, err := c.FindCurrentUserPrincipal() + if err != nil { + return nil, nil, fmt.Errorf("failed to query CardDAV principal: %v", err) + } + + homeSet, err = c.FindAddressBookHomeSet(principal) + if err != nil { + return nil, nil, fmt.Errorf("failed to query CardDAV address book home set: %v", err) + } + + p.homeSetCache[session.Username()] = homeSet + // TODO: evict entries from the cache if it's getting too big + } + + addressBooks, err := c.FindAddressBooks(homeSet) + if err != nil { + return nil, nil, fmt.Errorf("failed to query CardDAV address books: %v", err) + } + if len(addressBooks) == 0 { + return nil, nil, errNoAddressBook + } + return c, &addressBooks[0], nil +} + func newPlugin(srv *koushin.Server) (koushin.Plugin, error) { u, err := srv.Upstream("carddavs", "carddav+insecure", "https", "http+insecure") if _, ok := err.(*koushin.NoUpstreamError); ok { @@ -61,14 +99,18 @@ func newPlugin(srv *koushin.Server) (koushin.Plugin, error) { srv.Logger().Printf("Configured upstream CardDAV server: %v", u) - p := koushin.GoPlugin{Name: "carddav"} + p := &plugin{ + GoPlugin: koushin.GoPlugin{Name: "carddav"}, + url: u, + homeSetCache: make(map[string]string), + } - registerRoutes(&p, u) + registerRoutes(p) p.Inject("compose.html", func(ctx *koushin.Context, _data koushin.RenderData) error { data := _data.(*koushinbase.ComposeRenderData) - c, addressBook, err := getAddressBook(u, ctx.Session) + c, addressBook, err := p.clientWithAddressBook(ctx.Session) if err == errNoAddressBook { return nil } else if err != nil { diff --git a/plugins/carddav/routes.go b/plugins/carddav/routes.go index 82b729e..2f33852 100644 --- a/plugins/carddav/routes.go +++ b/plugins/carddav/routes.go @@ -3,7 +3,6 @@ package koushincarddav import ( "fmt" "net/http" - "net/url" "git.sr.ht/~emersion/koushin" "github.com/emersion/go-vcard" @@ -22,11 +21,11 @@ type AddressObjectRenderData struct { AddressObject *carddav.AddressObject } -func registerRoutes(p *koushin.GoPlugin, u *url.URL) { +func registerRoutes(p *plugin) { p.GET("/contacts", func(ctx *koushin.Context) error { queryText := ctx.QueryParam("query") - c, addressBook, err := getAddressBook(u, ctx.Session) + c, addressBook, err := p.clientWithAddressBook(ctx.Session) if err != nil { return err } @@ -70,7 +69,7 @@ func registerRoutes(p *koushin.GoPlugin, u *url.URL) { p.GET("/contacts/:uid", func(ctx *koushin.Context) error { uid := ctx.Param("uid") - c, addressBook, err := getAddressBook(u, ctx.Session) + c, addressBook, err := p.clientWithAddressBook(ctx.Session) if err != nil { return err }