Skip to content

Commit 4a67c4d

Browse files
committed
fix(go): handle HTML errors
1 parent a11e02e commit 4a67c4d

File tree

5 files changed

+121
-43
lines changed

5 files changed

+121
-43
lines changed

playground/go/ingestion.go

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,67 @@ package main
22

33
import (
44
"fmt"
5-
"time"
65

6+
"github.com/algolia/algoliasearch-client-go/v4/algolia/call"
77
"github.com/algolia/algoliasearch-client-go/v4/algolia/ingestion"
8+
"github.com/algolia/algoliasearch-client-go/v4/algolia/transport"
89
)
910

1011
func testIngestion(appID, apiKey string) int {
11-
ingestionClient, err := ingestion.NewClient(appID, apiKey, ingestion.US)
12+
ingestionClient, err := ingestion.NewClientWithConfig(ingestion.IngestionConfiguration{
13+
Configuration: transport.Configuration{
14+
AppID: appID,
15+
ApiKey: apiKey,
16+
Hosts: []transport.StatefulHost{
17+
transport.NewStatefulHost("http", "host.docker.internal:6676", call.IsReadWrite),
18+
},
19+
ExposeIntermediateNetworkErrors: true,
20+
},
21+
})
1222
if err != nil {
1323
panic(err)
1424
}
1525

26+
res, err := ingestionClient.CustomGet(ingestionClient.NewApiCustomGetRequest("1/rate-limit"))
27+
if err != nil {
28+
panic(err)
29+
}
30+
31+
fmt.Printf("Rate limit: %+v\n", res)
32+
33+
return 0
34+
1635
// another example to generate payload for a request.
17-
createAuthenticationResponse, err := ingestionClient.CreateAuthentication(ingestionClient.NewApiCreateAuthenticationRequest(
18-
&ingestion.AuthenticationCreate{
19-
Type: ingestion.AUTHENTICATION_TYPE_BASIC,
20-
Name: fmt.Sprintf("my-authentication-%d", time.Now().Unix()),
21-
Input: ingestion.AuthInput{
22-
AuthBasic: &ingestion.AuthBasic{
23-
Username: "username",
24-
Password: "password",
36+
/*
37+
createAuthenticationResponse, err := ingestionClient.CreateAuthentication(ingestionClient.NewApiCreateAuthenticationRequest(
38+
&ingestion.AuthenticationCreate{
39+
Type: ingestion.AUTHENTICATION_TYPE_BASIC,
40+
Name: fmt.Sprintf("my-authentication-%d", time.Now().Unix()),
41+
Input: ingestion.AuthInput{
42+
AuthBasic: &ingestion.AuthBasic{
43+
Username: "username",
44+
Password: "password",
45+
},
2546
},
26-
},
27-
}))
47+
}))
2848
29-
if err != nil {
30-
fmt.Printf("request error with CreateAuthentication: %v\n", err)
31-
return 1
32-
}
49+
if err != nil {
50+
fmt.Printf("request error with CreateAuthentication: %v\n", err)
51+
return 1
52+
}
3353
34-
printResponse(createAuthenticationResponse)
54+
printResponse(createAuthenticationResponse)
3555
36-
listAuthenticationsResponse, err := ingestionClient.ListAuthentications(
37-
ingestionClient.NewApiListAuthenticationsRequest().WithItemsPerPage(2),
38-
)
39-
if err != nil {
40-
fmt.Printf("request error with GetAuthentications: %v\n", err)
41-
return 1
42-
}
56+
listAuthenticationsResponse, err := ingestionClient.ListAuthentications(
57+
ingestionClient.NewApiListAuthenticationsRequest().WithItemsPerPage(2),
58+
)
59+
if err != nil {
60+
fmt.Printf("request error with GetAuthentications: %v\n", err)
61+
return 1
62+
}
4363
44-
printResponse(listAuthenticationsResponse)
64+
printResponse(listAuthenticationsResponse)
4565
46-
return 0
66+
return 0
67+
*/
4768
}

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)