internal: make Status a Text{Marshaler,Unmarshaler}

This commit is contained in:
Simon Ser 2020-01-15 19:23:09 +01:00
parent 040c38f1b6
commit 3d37e49ca0
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48

View File

@ -9,43 +9,46 @@ import (
"time" "time"
) )
// TODO: cache parsed value type Status struct {
type Status string Code int
Text string
func NewStatus(code int, msg string) Status {
if msg == "" {
msg = http.StatusText(code)
}
return Status(fmt.Sprintf("HTTP/1.1 %v %v", code, msg))
} }
func (s Status) parse() (int, string, error) { func (s *Status) MarshalText() ([]byte, error) {
if s == "" { text := s.Text
return http.StatusOK, "", nil if text == "" {
text = http.StatusText(s.Code)
}
return []byte(fmt.Sprintf("HTTP/1.1 %v %v", s.Code, s.Text)), nil
}
func (s *Status) UnmarshalText(b []byte) error {
if len(b) == 0 {
return nil
} }
parts := strings.SplitN(string(s), " ", 3) parts := strings.SplitN(string(b), " ", 3)
if len(parts) != 3 { if len(parts) != 3 {
return 0, "", fmt.Errorf("webdav: invalid HTTP status %q: expected 3 fields", s) return fmt.Errorf("webdav: invalid HTTP status %q: expected 3 fields", s)
} }
code, err := strconv.Atoi(parts[1]) code, err := strconv.Atoi(parts[1])
if err != nil { if err != nil {
return 0, "", fmt.Errorf("webdav: invalid HTTP status %q: failed to parse code: %v", s, err) return fmt.Errorf("webdav: invalid HTTP status %q: failed to parse code: %v", s, err)
} }
msg := parts[2]
return code, msg, nil s.Code = code
s.Text = parts[2]
return nil
} }
func (s Status) Err() error { func (s *Status) Err() error {
code, msg, err := s.parse() if s == nil {
if err != nil { return nil
return err
} }
// TODO: handle 2xx, 3xx // TODO: handle 2xx, 3xx
if code != http.StatusOK { if s.Code != http.StatusOK {
return fmt.Errorf("webdav: HTTP error: %v %v", code, msg) return fmt.Errorf("webdav: HTTP error: %v %v", s.Code, s.Text)
} }
return nil return nil
} }
@ -80,7 +83,7 @@ type Response struct {
Hrefs []string `xml:"href"` Hrefs []string `xml:"href"`
Propstats []Propstat `xml:"propstat,omitempty"` Propstats []Propstat `xml:"propstat,omitempty"`
ResponseDescription string `xml:"responsedescription,omitempty"` ResponseDescription string `xml:"responsedescription,omitempty"`
Status Status `xml:"status,omitempty"` Status *Status `xml:"status,omitempty"`
Error *RawXMLValue `xml:"error,omitempty"` Error *RawXMLValue `xml:"error,omitempty"`
Location *Location `xml:"location,omitempty"` Location *Location `xml:"location,omitempty"`
} }
@ -88,7 +91,7 @@ type Response struct {
func NewOKResponse(href string) *Response { func NewOKResponse(href string) *Response {
return &Response{ return &Response{
Hrefs: []string{href}, Hrefs: []string{href},
Status: NewStatus(http.StatusOK, ""), Status: &Status{Code: http.StatusOK},
} }
} }
@ -134,15 +137,14 @@ func (resp *Response) EncodeProp(code int, v interface{}) error {
for i := range resp.Propstats { for i := range resp.Propstats {
propstat := &resp.Propstats[i] propstat := &resp.Propstats[i]
c, _, _ := propstat.Status.parse() if propstat.Status.Code == code {
if c == code {
propstat.Prop.Raw = append(propstat.Prop.Raw, *raw) propstat.Prop.Raw = append(propstat.Prop.Raw, *raw)
return nil return nil
} }
} }
resp.Propstats = append(resp.Propstats, Propstat{ resp.Propstats = append(resp.Propstats, Propstat{
Status: NewStatus(code, ""), Status: Status{Code: code},
Prop: Prop{Raw: []RawXMLValue{*raw}}, Prop: Prop{Raw: []RawXMLValue{*raw}},
}) })
return nil return nil