@@ -17,12 +17,12 @@ import (
17
17
18
18
// APIError represents an api error response.
19
19
type APIError struct {
20
- StatusCode int `json:"status_code" xml:"StatusCode"` // HTTP status code
21
- Type string `json:"type" xml:"Type"` // Type of error
22
- Message string `json:"message" xml:"Message"` // Human-readable message
23
- Detail string `json:"detail,omitempty" xml:"Detail,omitempty" ` // Detailed error message
24
- Errors map [string ]interface {} `json:"errors,omitempty" xml:"Errors,omitempty" ` // Additional error details
25
- Raw string `json:"raw" xml:"Raw"` // Raw response body for debugging
20
+ StatusCode int `json:"status_code"` // HTTP status code
21
+ Type string `json:"type"` // Type of error
22
+ Message string `json:"message"` // Human-readable message
23
+ Detail string `json:"detail,omitempty"` // Detailed error message
24
+ Errors map [string ]interface {} `json:"errors,omitempty"` // Additional error details
25
+ Raw string `json:"raw"` // Raw response body for debugging
26
26
}
27
27
28
28
// Error returns a string representation of the APIError, making it compatible with the error interface.
@@ -46,14 +46,14 @@ func (e *APIError) Error() string {
46
46
func HandleAPIErrorResponse (resp * http.Response , log logger.Logger ) * APIError {
47
47
apiError := & APIError {
48
48
StatusCode : resp .StatusCode ,
49
- Type : "APIError " ,
49
+ Type : "API Error Response " ,
50
50
Message : "An error occurred" ,
51
51
}
52
52
53
53
bodyBytes , err := io .ReadAll (resp .Body )
54
54
if err != nil {
55
55
apiError .Raw = "Failed to read response body"
56
- logError ( log , apiError , "error_reading_response_body" , resp )
56
+ log . LogError ( "error_reading_response_body" , resp . Request . Method , resp . Request . URL . String (), apiError . StatusCode , resp . Status , err , apiError . Raw )
57
57
return apiError
58
58
}
59
59
@@ -70,7 +70,7 @@ func HandleAPIErrorResponse(resp *http.Response, log logger.Logger) *APIError {
70
70
default :
71
71
apiError .Raw = string (bodyBytes )
72
72
apiError .Message = "Unknown content type error"
73
- logError ( log , apiError , "unknown_content_type_error " , resp )
73
+ log . LogError ( "unknown_content_type_error" , resp . Request . Method , resp . Request . URL . String (), apiError . StatusCode , "Unknown content type " , nil , apiError . Raw )
74
74
}
75
75
76
76
return apiError
@@ -94,29 +94,27 @@ func ParseContentTypeHeader(header string) (string, map[string]string) {
94
94
func parseJSONResponse (bodyBytes []byte , apiError * APIError , log logger.Logger , resp * http.Response ) {
95
95
if err := json .Unmarshal (bodyBytes , apiError ); err != nil {
96
96
apiError .Raw = string (bodyBytes )
97
- log .LogError ("json_parsing_error" ,
98
- resp .Request .Method ,
99
- resp .Request .URL .String (),
100
- resp .StatusCode ,
101
- "JSON parsing failed" ,
102
- err ,
103
- apiError .Raw ,
104
- )
97
+ logError (log , apiError , "json_parsing_error" , resp .Request .Method , resp .Request .URL .String (), resp .Status , err )
105
98
} else {
106
- // Successfully parsed JSON error, so log the error details.
107
- logError (log , apiError , "json_error_detected" , resp )
99
+ if apiError .Message == "" {
100
+ apiError .Message = "An unknown error occurred"
101
+ }
102
+
103
+ // Log the detected JSON error with all the context information.
104
+ logError (log , apiError , "json_error_detected" , resp .Request .Method , resp .Request .URL .String (), resp .Status , nil )
108
105
}
109
106
}
110
107
111
108
// parseXMLResponse dynamically parses XML error responses and accumulates potential error messages.
112
109
func parseXMLResponse (bodyBytes []byte , apiError * APIError , log logger.Logger , resp * http.Response ) {
113
- // Always set the Raw field to the entire XML content for debugging purposes
110
+ // Always set the Raw field to the entire XML content for debugging purposes.
114
111
apiError .Raw = string (bodyBytes )
115
112
116
- // Parse the XML document
113
+ // Parse the XML document.
117
114
doc , err := xmlquery .Parse (bytes .NewReader (bodyBytes ))
118
115
if err != nil {
119
- logError (log , apiError , "xml_parsing_error" , resp )
116
+ // Log the XML parsing error with all the context information.
117
+ logError (log , apiError , "xml_parsing_error" , resp .Request .Method , resp .Request .URL .String (), resp .Status , err )
120
118
return
121
119
}
122
120
@@ -133,93 +131,121 @@ func parseXMLResponse(bodyBytes []byte, apiError *APIError, log logger.Logger, r
133
131
134
132
traverse (doc )
135
133
136
- // Concatenate all messages found in the XML for the 'Message' field of APIError
134
+ // Concatenate all messages found in the XML for the 'Message' field of APIError.
137
135
if len (messages ) > 0 {
138
136
apiError .Message = strings .Join (messages , "; " )
139
137
} else {
140
- // Fallback error message if no specific messages were extracted
141
138
apiError .Message = "Failed to extract error details from XML response"
142
139
}
143
140
144
- // Log the error using the centralized logger
145
- logError (log , apiError , "xml_error_detected" , resp )
141
+ // Determine the error to log based on whether a message was found.
142
+ var logErr error
143
+ if apiError .Message == "" {
144
+ logErr = fmt .Errorf ("No error message extracted from XML" )
145
+ }
146
+
147
+ // Log the error or the lack of extracted messages using the centralized logger.
148
+ logError (log , apiError , "xml_error_detected" , resp .Request .Method , resp .Request .URL .String (), resp .Status , logErr )
146
149
}
147
150
148
151
// parseTextResponse updates the APIError structure based on a plain text error response and logs it.
149
152
func parseTextResponse (bodyBytes []byte , apiError * APIError , log logger.Logger , resp * http.Response ) {
150
153
bodyText := string (bodyBytes )
151
- apiError .Message = bodyText
152
154
apiError .Raw = bodyText
153
- // Log the plain text error using the centralized logger.
154
- logError (log , apiError , "text_error_detected" , resp )
155
+
156
+ // Check if the 'Message' field of APIError is empty and use the body text as the message.
157
+ if apiError .Message == "" {
158
+ apiError .Message = bodyText
159
+ }
160
+
161
+ // Use the updated logError function with the additional parameters.
162
+ logError (log , apiError , "text_error_detected" , resp .Request .Method , resp .Request .URL .String (), resp .Status , nil )
155
163
}
156
164
157
165
// parseHTMLResponse extracts meaningful information from an HTML error response and concatenates all text within <p> tags.
158
166
func parseHTMLResponse (bodyBytes []byte , apiError * APIError , log logger.Logger , resp * http.Response ) {
159
- // Always set the Raw field to the entire HTML content for debugging purposes
167
+ // Always set the Raw field to the entire HTML content for debugging purposes.
160
168
apiError .Raw = string (bodyBytes )
161
169
162
170
reader := bytes .NewReader (bodyBytes )
163
171
doc , err := html .Parse (reader )
164
172
if err != nil {
165
- logError (log , apiError , "html_parsing_error" , resp )
173
+ // Log HTML parsing error using centralized logger with context.
174
+ logError (log , apiError , "html_parsing_error" , resp .Request .Method , resp .Request .URL .String (), resp .Status , err )
166
175
return
167
176
}
168
177
169
- var messages []string // To accumulate messages from all <p> tags
178
+ var messages []string // To accumulate messages from all <p> tags.
170
179
var parse func (* html.Node )
171
180
parse = func (n * html.Node ) {
172
181
if n .Type == html .ElementNode && n .Data == "p" {
173
182
var pText strings.Builder
174
183
for c := n .FirstChild ; c != nil ; c = c .NextSibling {
175
184
if c .Type == html .TextNode && strings .TrimSpace (c .Data ) != "" {
176
- // Build text content of <p> tag
185
+ // Build text content of <p> tag.
177
186
if pText .Len () > 0 {
178
- pText .WriteString (" " ) // Add a space between text nodes within the same <p> tag
187
+ pText .WriteString (" " ) // Add a space between text nodes within the same <p> tag.
179
188
}
180
189
pText .WriteString (strings .TrimSpace (c .Data ))
181
190
}
182
191
}
183
192
if pText .Len () > 0 {
184
- // Add the built text content of the <p> tag to messages
193
+ // Add the built text content of the <p> tag to messages.
185
194
messages = append (messages , pText .String ())
186
195
}
187
196
}
188
197
for c := n .FirstChild ; c != nil ; c = c .NextSibling {
189
- parse (c ) // Recursively parse the document
198
+ parse (c ) // Recursively parse the document.
190
199
}
191
200
}
192
201
193
202
parse (doc )
194
203
195
- // Concatenate all accumulated messages with a separator
204
+ // Concatenate all accumulated messages with a separator.
196
205
if len (messages ) > 0 {
197
206
apiError .Message = strings .Join (messages , "; " )
198
207
} else {
199
- // Fallback error message if no specific messages were extracted
208
+ // Fallback error message if no specific messages were extracted.
200
209
apiError .Message = "HTML Error: See 'Raw' field for details."
201
210
}
202
211
203
- // Log the extracted error message or the fallback message
204
- logError (log , apiError , "html_error_detected" , resp )
212
+ // Determine the error to log based on whether a message was found.
213
+ var logErr error
214
+ if apiError .Message == "" {
215
+ logErr = fmt .Errorf ("No error message extracted from HTML" )
216
+ }
217
+
218
+ // Log the extracted error message or the fallback message using the centralized logger.
219
+ logError (log , apiError , "html_error_detected" , resp .Request .Method , resp .Request .URL .String (), resp .Status , logErr )
205
220
}
206
221
207
222
// logError logs the error details using the provided logger instance.
208
- func logError (log logger.Logger , apiError * APIError , event string , resp * http.Response ) {
223
+ // func logError(log logger.Logger, apiError *APIError, event string, resp *http.Response) {
224
+ // // Prepare the error message. If apiError.Message is empty, use a default message.
225
+ // errorMessage := apiError.Message
226
+ // if errorMessage == "" {
227
+ // errorMessage = "An unspecified error occurred"
228
+ // }
229
+
230
+ // // Use LogError method from the logger package for error logging.
231
+ // log.LogError(
232
+ // event,
233
+ // resp.Request.Method,
234
+ // resp.Request.URL.String(),
235
+ // apiError.StatusCode,
236
+ // resp.Status,
237
+ // fmt.Errorf(errorMessage),
238
+ // apiError.Raw,
239
+ // )
240
+ // }
241
+
242
+ func logError (log logger.Logger , apiError * APIError , event , method , url , statusMessage string , err error ) {
209
243
// Prepare the error message. If apiError.Message is empty, use a default message.
210
244
errorMessage := apiError .Message
211
245
if errorMessage == "" {
212
246
errorMessage = "An unspecified error occurred"
213
247
}
214
248
215
- // Use LogError method from the logger package for error logging.
216
- log .LogError (
217
- event ,
218
- resp .Request .Method ,
219
- resp .Request .URL .String (),
220
- apiError .StatusCode ,
221
- resp .Status ,
222
- fmt .Errorf (errorMessage ),
223
- apiError .Raw ,
224
- )
249
+ // Call the LogError method from the logger package for error logging.
250
+ log .LogError (event , method , url , apiError .StatusCode , statusMessage , err , apiError .Raw )
225
251
}
0 commit comments