diff --git a/body.go b/body.go index e98e28e..53bf6c4 100644 --- a/body.go +++ b/body.go @@ -3,6 +3,7 @@ package requests import ( "bytes" "encoding/json" + "encoding/xml" "io" "net/url" "os" @@ -57,6 +58,17 @@ func BodyJSON(v any) BodyGetter { } } +// BodyXML is a BodyGetter that marshals a XML object. +func BodyXML(v any) BodyGetter { + return func() (io.ReadCloser, error) { + b, err := xml.Marshal(v) + if err != nil { + return nil, err + } + return core.RC(bytes.NewReader(b)), nil + } +} + // BodyForm is a BodyGetter that builds an encoded form body. func BodyForm(data url.Values) BodyGetter { return func() (r io.ReadCloser, err error) { diff --git a/builder_core.go b/builder_core.go index e1db833..26490dd 100644 --- a/builder_core.go +++ b/builder_core.go @@ -54,8 +54,8 @@ import ( // If no validator has been added, Builder will use [DefaultValidator]. // // Set a handler for a response with [Builder.Handle] -// or use the built in [Builder.ToHeaders], [Builder.ToJSON], [Builder.ToString], -// [Builder.ToBytesBuffer], or [Builder.ToWriter]. +// or use the built in [Builder.ToHeaders], [Builder.ToJSON], [Builder.ToXML], +// [Builder.ToString], [Builder.ToBytesBuffer], or [Builder.ToWriter]. // // [Builder.Fetch] creates an http.Request with [Builder.Request] // and validates and handles it with [Builder.Do]. diff --git a/builder_extras.go b/builder_extras.go index ec833a9..7fb2e62 100644 --- a/builder_extras.go +++ b/builder_extras.go @@ -118,6 +118,14 @@ func (rb *Builder) BodyJSON(v any) *Builder { ContentType("application/json") } +// BodyXML sets the Builder's request body to the marshaled XML. +// It also sets ContentType to "application/xml". +func (rb *Builder) BodyXML(v any) *Builder { + return rb. + Body(BodyXML(v)). + ContentType("application/xml") +} + // BodyForm sets the Builder's request body to the encoded form. // It also sets the ContentType to "application/x-www-form-urlencoded". func (rb *Builder) BodyForm(data url.Values) *Builder { @@ -151,6 +159,11 @@ func (rb *Builder) ToJSON(v any) *Builder { return rb.Handle(ToJSON(v)) } +// ToXML sets the Builder to decode a response as an XML object +func (rb *Builder) ToXML(v any) *Builder { + return rb.Handle(ToXML(v)) +} + // ToString sets the Builder to write the response body to the provided string pointer. func (rb *Builder) ToString(sp *string) *Builder { return rb.Handle(ToString(sp)) diff --git a/handler.go b/handler.go index 31fb9f8..e0d990c 100644 --- a/handler.go +++ b/handler.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "encoding/json" + "encoding/xml" "io" "net/http" "os" @@ -53,6 +54,20 @@ func ToJSON(v any) ResponseHandler { } } +// ToXML decodes a response as an XML object. +func ToXML(v any) ResponseHandler { + return func(res *http.Response) error { + data, err := io.ReadAll(res.Body) + if err != nil { + return err + } + if err = xml.Unmarshal(data, v); err != nil { + return err + } + return nil + } +} + // ToString writes the response body to the provided string pointer. func ToString(sp *string) ResponseHandler { return func(res *http.Response) error { diff --git a/validator_handler.go b/validator_handler.go index 92256c6..909741d 100644 --- a/validator_handler.go +++ b/validator_handler.go @@ -32,3 +32,10 @@ var ErrInvalidHandled = errors.New("handled recovery from invalid response") func ErrorJSON(v any) ResponseHandler { return ValidatorHandler(DefaultValidator, ToJSON(v)) } + +// ErrorXML is a ValidatorHandler that applies DefaultValidator +// and decodes the response as an XML object +// if the DefaultValidator check fails. +func ErrorXML(v any) ResponseHandler { + return ValidatorHandler(DefaultValidator, ToXML(v)) +}