Skip to content

Commit d5412b6

Browse files
rvilgalyscopybara-github
authored andcommitted
Improves API error output for better debugging.
PiperOrigin-RevId: 629172132
1 parent 81fe633 commit d5412b6

File tree

6 files changed

+812
-7
lines changed

6 files changed

+812
-7
lines changed

README.md

+3-6
Original file line numberDiff line numberDiff line change
@@ -224,18 +224,15 @@ For testing the blocklists, you can use the following URLs:
224224

225225
## 4XX Errors
226226

227-
If you start the client without proper credentials or project set up, you will
228-
see an error similar to what is shown below on startup:
227+
If you start the client without proper credentials or project set up, you will see an error similar to what is shown below on startup:
229228

230229
```
231230
webrisk: 2023/01/27 19:36:13 database.go:217: ListUpdate failure (1): webrisk: unexpected server response code: 400
232231
```
233232

234-
For 400 errors, this usually means the API key is incorrect or was not supplied
235-
correctly.
233+
For 400 errors, this usually means the API key is incorrect or was not supplied correctly.
236234

237-
For 403 errors, this could mean the Web Risk API is not enabled for your project
238-
**or** your project does not have Billing enabled.
235+
For 403 errors, this could mean the Web Risk API is not enabled for your project **or** your project does not have Billing enabled.
239236

240237
# About the Social Engineering Extended Coverage List
241238

api.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"google.golang.org/protobuf/encoding/protojson"
2626
"google.golang.org/protobuf/proto"
27+
err_pb "github.com/google/webrisk/internal/http_error_proto"
2728
pb "github.com/google/webrisk/internal/webrisk_proto"
2829
)
2930

@@ -97,7 +98,7 @@ func (a *netAPI) doRequest(ctx context.Context, urlString string, resp proto.Mes
9798
}
9899
defer httpResp.Body.Close()
99100
if httpResp.StatusCode != 200 {
100-
return fmt.Errorf("webrisk: unexpected server response code: %d", httpResp.StatusCode)
101+
return a.parseError(httpResp)
101102
}
102103
body, err := ioutil.ReadAll(httpResp.Body)
103104
if err != nil {
@@ -106,6 +107,21 @@ func (a *netAPI) doRequest(ctx context.Context, urlString string, resp proto.Mes
106107
return protojson.Unmarshal(body, resp)
107108
}
108109

110+
// parseError parses an error JSON body and returns an error summary.
111+
func (a *netAPI) parseError(httpResp *http.Response) error {
112+
body, err := ioutil.ReadAll(httpResp.Body)
113+
if err != nil {
114+
return err
115+
}
116+
ep := new(err_pb.Error)
117+
o := protojson.UnmarshalOptions{DiscardUnknown: true, AllowPartial: true}
118+
if err := o.Unmarshal(body, ep); err != nil {
119+
return fmt.Errorf("webrisk: unknown error, response code: %d", httpResp.StatusCode)
120+
}
121+
return fmt.Errorf("webrisk: unexpected server response code: %d, status: %s, message: %s",
122+
httpResp.StatusCode, ep.GetError().GetStatus(), ep.GetError().GetMessage())
123+
}
124+
109125
// ListUpdate issues a ComputeThreatListDiff API call and returns the response.
110126
func (a *netAPI) ListUpdate(ctx context.Context, threatType pb.ThreatType, versionToken []byte,
111127
compressionTypes []pb.CompressionType) (*pb.ComputeThreatListDiffResponse, error) {

api_test.go

+70
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@
1414
package webrisk
1515

1616
import (
17+
"bytes"
1718
"context"
1819
"encoding/base64"
20+
"errors"
21+
"io"
22+
"io/ioutil"
1923
"net/http"
2024
"net/http/httptest"
2125
"reflect"
2226
"testing"
2327

28+
"github.com/google/go-cmp/cmp"
29+
"github.com/google/go-cmp/cmp/cmpopts"
2430
"google.golang.org/protobuf/encoding/protojson"
2531
"google.golang.org/protobuf/proto"
2632
pb "github.com/google/webrisk/internal/webrisk_proto"
@@ -182,3 +188,67 @@ func TestNetAPI(t *testing.T) {
182188
t.Errorf("unexpected HashLookup success, wanted malformed JSON error")
183189
}
184190
}
191+
192+
func createBody(j string) io.ReadCloser {
193+
return ioutil.NopCloser(bytes.NewReader([]byte(j)))
194+
}
195+
196+
func TestParseError(t *testing.T) {
197+
tests := []struct {
198+
httpResp *http.Response
199+
wantErr error
200+
}{
201+
{
202+
httpResp: &http.Response{
203+
StatusCode: http.StatusBadRequest,
204+
Body: createBody(`{
205+
"error": {
206+
"code": 400,
207+
"message": "API key not valid. Please pass a valid API key",
208+
"status": "INVALID_ARGUMENT"}}`), // Formatted Response
209+
},
210+
wantErr: errors.New("webrisk: unexpected server response code: 400, status: INVALID_ARGUMENT, message: API key not valid. Please pass a valid API key"),
211+
},
212+
{
213+
httpResp: &http.Response{
214+
StatusCode: http.StatusForbidden,
215+
Body: createBody(`{
216+
"error": {
217+
"code": 403,
218+
"message": "API Not Enabled",
219+
"status": "PERMISSION_DENIED",
220+
"details": [{
221+
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
222+
"reason": "PERMISSION_DENIED",
223+
"domain": "googleapis.com",
224+
"metadata": {
225+
"service": "webrisk.googleapis.com"
226+
}}]}}`), // Full Response
227+
},
228+
wantErr: errors.New("webrisk: unexpected server response code: 403, status: PERMISSION_DENIED, message: API Not Enabled"),
229+
},
230+
{
231+
httpResp: &http.Response{
232+
StatusCode: http.StatusServiceUnavailable,
233+
Body: createBody(""), // Empty body
234+
},
235+
wantErr: errors.New("webrisk: unknown error, response code: 503"),
236+
},
237+
{
238+
httpResp: &http.Response{
239+
StatusCode: http.StatusInternalServerError,
240+
Body: createBody(`{badjson}`),
241+
},
242+
wantErr: errors.New("webrisk: unknown error, response code: 500"),
243+
},
244+
}
245+
246+
for _, tc := range tests {
247+
var a netAPI
248+
gotErr := a.parseError(tc.httpResp)
249+
250+
if cmp.Equal(tc.wantErr, gotErr, cmpopts.EquateErrors()) {
251+
t.Errorf("parseError(%v) returned error: %v, want error: %v", tc.httpResp, gotErr, tc.wantErr)
252+
}
253+
}
254+
}

0 commit comments

Comments
 (0)