internal: introduce DecodeXMLRequest, ServeXML and ServeMultistatus

This commit is contained in:
Simon Ser 2020-01-19 11:12:45 +01:00
parent 60e5d57cda
commit f3f1c8b58a
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
2 changed files with 30 additions and 23 deletions

View File

@ -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 {

View File

@ -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)