Skip to content

Commit

Permalink
fix(go): handle HTML errors [skip-bc] (#4096)
Browse files Browse the repository at this point in the history
  • Loading branch information
millotp committed Nov 18, 2024
1 parent 4b26711 commit 02793f7
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 17 deletions.
14 changes: 1 addition & 13 deletions templates/go/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -459,19 +459,7 @@ func (c *APIClient) {{nickname}}({{#hasParams}}r {{#structPrefix}}{{&classname}}
}

if res.StatusCode >= 300 {
newErr := &APIError{
Message: string(resBody),
Status: res.StatusCode,
}

var v ErrorBase
err = c.decode(&v, resBody)
if err != nil {
newErr.Message = err.Error()
return {{#returnType}}returnValue, {{/returnType}}newErr
}

return {{#returnType}}returnValue, {{/returnType}}newErr
return {{#returnType}}returnValue, {{/returnType}}c.decodeError(res, resBody)
}

{{#returnType}}
Expand Down
73 changes: 71 additions & 2 deletions templates/go/client.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ func (c *APIClient) decode(v any, b []byte) error {
return fmt.Errorf("failed to unmarshal one of in response body: %w", err)
}
} else {
return errors.New("Unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined")
return errors.New("unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined")
}
} else if err := json.Unmarshal(b, v); err != nil { // simple model
return fmt.Errorf("failed to unmarshal response body: %w", err)
Expand All @@ -243,6 +243,33 @@ func (c *APIClient) decode(v any, b []byte) error {
return nil
}

func (c *APIClient) decodeError(res *http.Response, body []byte) error {
apiErr := &APIError{
Message: string(body), // default to the full body if we cannot guess the type of the error.
Status: res.StatusCode,
}

if strings.Contains(res.Header.Get("Content-Type"), "application/json") {
var errBase ErrorBase
err := c.decode(&errBase, body)
if err != nil {
apiErr.Message = err.Error()
return apiErr
}
if errBase.Message != nil {
apiErr.Message = *errBase.Message
}

apiErr.AdditionalProperties = errBase.AdditionalProperties
} else if strings.Contains(res.Header.Get("Content-Type"), "text/html") {
apiErr.Message = http.StatusText(res.StatusCode)
}

return apiErr
}

// Prevent trying to import "fmt"
func reportError(format string, a ...any) error {
return fmt.Errorf(format, a...)
Expand Down Expand Up @@ -299,16 +326,58 @@ func setBody(body any, c compression.Compression) (*bytes.Buffer, error) {
}

if bodyBuf.Len() == 0 {
return nil, errors.New("Invalid body type, or empty body")
return nil, errors.New("invalid body type, or empty body")
}
return bodyBuf, nil
}

type APIError struct {
Message string
Status int
AdditionalProperties map[string]any
}

func (e APIError) Error() string {
return fmt.Sprintf("API error [%d] %s", e.Status, e.Message)
}

func (o APIError) MarshalJSON() ([]byte, error) {
toSerialize := map[string]any{
"message": o.Message,
}

for key, value := range o.AdditionalProperties {
toSerialize[key] = value
}

serialized, err := json.Marshal(toSerialize)
if err != nil {
return nil, fmt.Errorf("failed to marshal APIError: %w", err)
}

return serialized, nil
}

func (o *APIError) UnmarshalJSON(bytes []byte) error {
type _APIError APIError
apiErr := _APIError{}

err := json.Unmarshal(bytes, &apiErr)
if err != nil {
return fmt.Errorf("failed to unmarshal APIError: %w", err)
}

*o = APIError(apiErr)

additionalProperties := make(map[string]any)

err = json.Unmarshal(bytes, &additionalProperties)
if err != nil {
return fmt.Errorf("failed to unmarshal additionalProperties in APIError: %w", err)
}

delete(additionalProperties, "message")
o.AdditionalProperties = additionalProperties

return nil
}
2 changes: 1 addition & 1 deletion tests/CTS/client/search/indexExists.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"expected": {
"error": {
"csharp": "{\\\"message\\\":\\\"Invalid API key\\\"}",
"go": "API error [403] {\\\"message\\\":\\\"Invalid API key\\\"}",
"go": "API error [403] Invalid API key",
"java": "Status Code: 403 - {\\\"message\\\":\\\"Invalid API key\\\"}",
"javascript": "Invalid API key",
"kotlin": "Client request(GET http://%localhost%:6681/1/indexes/indexExistsERROR/settings) invalid: 403 Forbidden. Text: \\\"{\\\"message\\\":\\\"Invalid API key\\\"}\\\"",
Expand Down
2 changes: 1 addition & 1 deletion tests/CTS/client/search/saveObjects.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"expected": {
"error": {
"csharp": "{\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}",
"go": "API error [403] {\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}",
"go": "API error [403] Invalid Application-ID or API key",
"java": "Status Code: 403 - {\\\"message\\\":\\\"Invalid Application-ID or API key\\\",\\\"status\\\":403}",
"javascript": "Invalid Application-ID or API key",
"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}\\\"",
Expand Down

0 comments on commit 02793f7

Please sign in to comment.