@@ -78,7 +78,13 @@ func (c *Client) send(method, url string, headers map[string]string, body []byte
7878 }
7979 case formatXML :
8080 if _ , err := plist .Unmarshal (normalizePlist (data ), out ); err != nil {
81- return nil , fmt .Errorf ("decode plist: %w" , err )
81+ return nil , & ResponseDecodeError {
82+ Cause : err ,
83+ StatusCode : res .StatusCode ,
84+ ContentType : res .Header .Get ("Content-Type" ),
85+ Body : truncateBody (data , 500 ),
86+ URLs : extractURLs (data ),
87+ }
8288 }
8389 }
8490
@@ -124,3 +130,41 @@ func normalizePlist(body []byte) []byte {
124130
125131 return n
126132}
133+
134+ type ResponseDecodeError struct {
135+ Cause error
136+ StatusCode int
137+ ContentType string
138+ Body string
139+ URLs []string
140+ }
141+
142+ func (e * ResponseDecodeError ) Error () string {
143+ return fmt .Sprintf ("failed to unmarshal xml: %v" , e .Cause )
144+ }
145+
146+ func (e * ResponseDecodeError ) Unwrap () error {
147+ return e .Cause
148+ }
149+
150+ var urlPattern = regexp .MustCompile (`https?://[^\s"'<>]+` )
151+
152+ func extractURLs (body []byte ) []string {
153+ matches := urlPattern .FindAll (body , - 1 )
154+
155+ urls := make ([]string , 0 , len (matches ))
156+ for _ , match := range matches {
157+ urls = append (urls , string (match ))
158+ }
159+
160+ return urls
161+ }
162+
163+ func truncateBody (body []byte , max int ) string {
164+ trimmed := strings .TrimSpace (string (body ))
165+ if len (trimmed ) <= max {
166+ return trimmed
167+ }
168+
169+ return trimmed [:max ] + "..."
170+ }
0 commit comments