caldav: implement handleMultiget()

The implementation has feature parity with the CardDAV one.
This commit is contained in:
Conrad Hoffmann 2022-03-31 11:28:26 +02:00 committed by Simon Ser
parent 585b01a7a8
commit 303aef52f3

View File

@ -85,7 +85,7 @@ func (h *Handler) handleReport(w http.ResponseWriter, r *http.Request) error {
if report.Query != nil { if report.Query != nil {
return h.handleQuery(r, w, report.Query) return h.handleQuery(r, w, report.Query)
} else if report.Multiget != nil { } else if report.Multiget != nil {
return h.handleMultiget(w, report.Multiget) return h.handleMultiget(r.Context(), w, report.Multiget)
} }
return internal.HTTPErrorf(http.StatusBadRequest, "caldav: expected calendar-query or calendar-multiget element in REPORT request") return internal.HTTPErrorf(http.StatusBadRequest, "caldav: expected calendar-query or calendar-multiget element in REPORT request")
} }
@ -158,6 +158,44 @@ func decodeCompFilter(el *compFilter) (*CompFilter, error) {
return cf, nil return cf, nil
} }
func decodeComp(comp *comp) (*CalendarCompRequest, error) {
if comp == nil {
return nil, internal.HTTPErrorf(http.StatusBadRequest, "caldav: unexpected empty calendar-data in request")
}
if comp.Allprop != nil && len(comp.Prop) > 0 {
return nil, internal.HTTPErrorf(http.StatusBadRequest, "caldav: only one of allprop or prop can be specified in calendar-data")
}
if comp.Allcomp != nil && len(comp.Comp) > 0 {
return nil, internal.HTTPErrorf(http.StatusBadRequest, "caldav: only one of allcomp or comp can be specified in calendar-data")
}
req := &CalendarCompRequest{
AllProps: comp.Allprop != nil,
AllComps: comp.Allcomp != nil,
}
for _, p := range comp.Prop {
req.Props = append(req.Props, p.Name)
}
for _, c := range comp.Comp {
comp, err := decodeComp(&c)
if err != nil {
return nil, err
}
req.Comps = append(req.Comps, *comp)
}
return req, nil
}
func decodeCalendarDataReq(calendarData *calendarDataReq) (*CalendarCompRequest, error) {
if calendarData.Comp == nil {
return &CalendarCompRequest{
AllProps: true,
AllComps: true,
}, nil
}
return decodeComp(calendarData.Comp)
}
func (h *Handler) handleQuery(r *http.Request, w http.ResponseWriter, query *calendarQuery) error { func (h *Handler) handleQuery(r *http.Request, w http.ResponseWriter, query *calendarQuery) error {
var q CalendarQuery var q CalendarQuery
// TODO: calendar-data in query.Prop // TODO: calendar-data in query.Prop
@ -192,8 +230,44 @@ func (h *Handler) handleQuery(r *http.Request, w http.ResponseWriter, query *cal
return internal.ServeMultistatus(w, ms) return internal.ServeMultistatus(w, ms)
} }
func (h *Handler) handleMultiget(w http.ResponseWriter, multiget *calendarMultiget) error { func (h *Handler) handleMultiget(ctx context.Context, w http.ResponseWriter, multiget *calendarMultiget) error {
panic("TODO") var dataReq CalendarCompRequest
if multiget.Prop != nil {
var calendarData calendarDataReq
if err := multiget.Prop.Decode(&calendarData); err != nil && !internal.IsNotFound(err) {
return err
}
decoded, err := decodeCalendarDataReq(&calendarData)
if err != nil {
return err
}
dataReq = *decoded
}
var resps []internal.Response
for _, href := range multiget.Hrefs {
co, err := h.Backend.GetCalendarObject(ctx, href.Path, &dataReq)
if err != nil {
resp := internal.NewErrorResponse(href.Path, err)
resps = append(resps, *resp)
continue
}
b := backend{h.Backend}
propfind := internal.Propfind{
Prop: multiget.Prop,
AllProp: multiget.AllProp,
PropName: multiget.PropName,
}
resp, err := b.propfindCalendarObject(ctx, &propfind, co)
if err != nil {
return err
}
resps = append(resps, *resp)
}
ms := internal.NewMultistatus(resps...)
return internal.ServeMultistatus(w, ms)
} }
type backend struct { type backend struct {