From f3f1c8b58a36a4b7ebf790798cd5ca30c05bfe7a Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 19 Jan 2020 11:12:45 +0100 Subject: [PATCH] internal: introduce DecodeXMLRequest, ServeXML and ServeMultistatus --- carddav/server.go | 15 +++------------ internal/server.go | 38 +++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/carddav/server.go b/carddav/server.go index 5bb49e9..581842f 100644 --- a/carddav/server.go +++ b/carddav/server.go @@ -2,7 +2,6 @@ package carddav import ( "encoding/xml" - "mime" "net/http" "github.com/emersion/go-vcard" @@ -42,14 +41,9 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func (h *Handler) handleReport(w http.ResponseWriter, r *http.Request) error { - t, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) - if t != "application/xml" && t != "text/xml" { - return internal.HTTPErrorf(http.StatusBadRequest, "webdav: expected application/xml REPORT request") - } - var report reportReq - if err := xml.NewDecoder(r.Body).Decode(&report); err != nil { - return &internal.HTTPError{http.StatusBadRequest, err} + if err := internal.DecodeXMLRequest(r, &report); err != nil { + return err } if report.Query != nil { @@ -87,10 +81,7 @@ func (h *Handler) handleMultiget(w http.ResponseWriter, multiget *addressbookMul ms := internal.NewMultistatus(resps...) - w.Header().Add("Content-Type", "text/xml; charset=\"utf-8\"") - w.WriteHeader(http.StatusMultiStatus) - w.Write([]byte(xml.Header)) - return xml.NewEncoder(w).Encode(&ms) + return internal.ServeMultistatus(w, ms) } type backend struct { diff --git a/internal/server.go b/internal/server.go index 55e4f18..584c0cb 100644 --- a/internal/server.go +++ b/internal/server.go @@ -45,6 +45,30 @@ func ServeError(w http.ResponseWriter, err error) { http.Error(w, err.Error(), code) } +func DecodeXMLRequest(r *http.Request, v interface{}) error { + t, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) + if t != "application/xml" && t != "text/xml" { + return HTTPErrorf(http.StatusBadRequest, "webdav: expected application/xml request") + } + + if err := xml.NewDecoder(r.Body).Decode(v); err != nil { + return &HTTPError{http.StatusBadRequest, err} + } + return nil +} + +func ServeXML(w http.ResponseWriter) *xml.Encoder { + w.Header().Add("Content-Type", "text/xml; charset=\"utf-8\"") + w.Write([]byte(xml.Header)) + return xml.NewEncoder(w) +} + +func ServeMultistatus(w http.ResponseWriter, ms *Multistatus) error { + // TODO: streaming + w.WriteHeader(http.StatusMultiStatus) + return ServeXML(w).Encode(ms) +} + type Backend interface { Options(r *http.Request) ([]string, error) HeadGet(w http.ResponseWriter, r *http.Request) error @@ -94,14 +118,9 @@ func (h *Handler) handleOptions(w http.ResponseWriter, r *http.Request) error { } func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request) error { - t, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) - if t != "application/xml" && t != "text/xml" { - return HTTPErrorf(http.StatusBadRequest, "webdav: expected application/xml PROPFIND request") - } - var propfind Propfind - if err := xml.NewDecoder(r.Body).Decode(&propfind); err != nil { - return &HTTPError{http.StatusBadRequest, err} + if err := DecodeXMLRequest(r, &propfind); err != nil { + return err } depth := DepthInfinity @@ -118,10 +137,7 @@ func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request) error { return err } - w.Header().Add("Content-Type", "text/xml; charset=\"utf-8\"") - w.WriteHeader(http.StatusMultiStatus) - w.Write([]byte(xml.Header)) - return xml.NewEncoder(w).Encode(&ms) + return ServeMultistatus(w, ms) } type PropfindFunc func(raw *RawXMLValue) (interface{}, error)