Skip to content

Commit fd69cf2

Browse files
authored
fix(go): handle HTML errors [skip-bc] (#4096)
1 parent a11e02e commit fd69cf2

File tree

4 files changed

+74
-17
lines changed

4 files changed

+74
-17
lines changed

templates/go/api.mustache

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -459,19 +459,7 @@ func (c *APIClient) {{nickname}}({{#hasParams}}r {{#structPrefix}}{{&classname}}
459459
}
460460

461461
if res.StatusCode >= 300 {
462-
newErr := &APIError{
463-
Message: string(resBody),
464-
Status: res.StatusCode,
465-
}
466-
467-
var v ErrorBase
468-
err = c.decode(&v, resBody)
469-
if err != nil {
470-
newErr.Message = err.Error()
471-
return {{#returnType}}returnValue, {{/returnType}}newErr
472-
}
473-
474-
return {{#returnType}}returnValue, {{/returnType}}newErr
462+
return {{#returnType}}returnValue, {{/returnType}}c.decodeError(res, resBody)
475463
}
476464

477465
{{#returnType}}

templates/go/client.mustache

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ func (c *APIClient) decode(v any, b []byte) error {
234234
return fmt.Errorf("failed to unmarshal one of in response body: %w", err)
235235
}
236236
} else {
237-
return errors.New("Unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined")
237+
return errors.New("unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined")
238238
}
239239
} else if err := json.Unmarshal(b, v); err != nil { // simple model
240240
return fmt.Errorf("failed to unmarshal response body: %w", err)
@@ -243,6 +243,33 @@ func (c *APIClient) decode(v any, b []byte) error {
243243
return nil
244244
}
245245

246+
func (c *APIClient) decodeError(res *http.Response, body []byte) error {
247+
apiErr := &APIError{
248+
Message: string(body), // default to the full body if we cannot guess the type of the error.
249+
Status: res.StatusCode,
250+
}
251+
252+
if strings.Contains(res.Header.Get("Content-Type"), "application/json") {
253+
var errBase ErrorBase
254+
255+
err := c.decode(&errBase, body)
256+
if err != nil {
257+
apiErr.Message = err.Error()
258+
259+
return apiErr
260+
}
261+
if errBase.Message != nil {
262+
apiErr.Message = *errBase.Message
263+
}
264+
265+
apiErr.AdditionalProperties = errBase.AdditionalProperties
266+
} else if strings.Contains(res.Header.Get("Content-Type"), "text/html") {
267+
apiErr.Message = http.StatusText(res.StatusCode)
268+
}
269+
270+
return apiErr
271+
}
272+
246273
// Prevent trying to import "fmt"
247274
func reportError(format string, a ...any) error {
248275
return fmt.Errorf(format, a...)
@@ -299,16 +326,58 @@ func setBody(body any, c compression.Compression) (*bytes.Buffer, error) {
299326
}
300327

301328
if bodyBuf.Len() == 0 {
302-
return nil, errors.New("Invalid body type, or empty body")
329+
return nil, errors.New("invalid body type, or empty body")
303330
}
304331
return bodyBuf, nil
305332
}
306333

307334
type APIError struct {
308335
Message string
309336
Status int
337+
AdditionalProperties map[string]any
310338
}
311339

312340
func (e APIError) Error() string {
313341
return fmt.Sprintf("API error [%d] %s", e.Status, e.Message)
314342
}
343+
344+
func (o APIError) MarshalJSON() ([]byte, error) {
345+
toSerialize := map[string]any{
346+
"message": o.Message,
347+
}
348+
349+
for key, value := range o.AdditionalProperties {
350+
toSerialize[key] = value
351+
}
352+
353+
serialized, err := json.Marshal(toSerialize)
354+
if err != nil {
355+
return nil, fmt.Errorf("failed to marshal APIError: %w", err)
356+
}
357+
358+
return serialized, nil
359+
}
360+
361+
func (o *APIError) UnmarshalJSON(bytes []byte) error {
362+
type _APIError APIError
363+
apiErr := _APIError{}
364+
365+
err := json.Unmarshal(bytes, &apiErr)
366+
if err != nil {
367+
return fmt.Errorf("failed to unmarshal APIError: %w", err)
368+
}
369+
370+
*o = APIError(apiErr)
371+
372+
additionalProperties := make(map[string]any)
373+
374+
err = json.Unmarshal(bytes, &additionalProperties)
375+
if err != nil {
376+
return fmt.Errorf("failed to unmarshal additionalProperties in APIError: %w", err)
377+
}
378+
379+
delete(additionalProperties, "message")
380+
o.AdditionalProperties = additionalProperties
381+
382+
return nil
383+
}

tests/CTS/client/search/indexExists.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
"expected": {
8383
"error": {
8484
"csharp": "{\\\"message\\\":\\\"Invalid API key\\\"}",
85-
"go": "API error [403] {\\\"message\\\":\\\"Invalid API key\\\"}",
85+
"go": "API error [403] Invalid API key",
8686
"java": "Status Code: 403 - {\\\"message\\\":\\\"Invalid API key\\\"}",
8787
"javascript": "Invalid API key",
8888
"kotlin": "Client request(GET http://%localhost%:6681/1/indexes/indexExistsERROR/settings) invalid: 403 Forbidden. Text: \\\"{\\\"message\\\":\\\"Invalid API key\\\"}\\\"",

tests/CTS/client/search/saveObjects.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
"expected": {
8282
"error": {
8383
"csharp": "{\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}",
84-
"go": "API error [403] {\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}",
84+
"go": "API error [403] Invalid Application-ID or API key",
8585
"java": "Status Code: 403 - {\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}",
8686
"javascript": "Invalid Application-ID or API key",
8787
"kotlin": "Client request(POST http://%localhost%:6680/1/indexes/cts_e2e_saveObjects_kotlin/batch) invalid: 403 Forbidden. Text: \\\"{\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}\\\"",

0 commit comments

Comments
 (0)