func TestDecodeJSON(t *testing.T) { testcases := []usererrors.UserError{ 0: usererrors.InvalidParams{{ Params: []string{"foo"}, Message: "hi there!", }}, 1: usererrors.InternalFailure{"myid"}, 2: usererrors.ActionNotAllowed{"doit"}, 3: usererrors.NotFound{}, 4: usererrors.BearerAuthRequired{}, 5: usererrors.AuthInvalid{}, } for i, testcase := range testcases { encoded, err := usererrors.MarshalJSON(testcase) t.Log(string(encoded)) res, err := usererrors.UnmarshalJSON(encoded) if err != nil { t.Errorf("%d: %s", i, err) } else if !reflect.DeepEqual(res, testcase) { t.Errorf("%d: err=%#v, expected %#v", i, res, testcase) } } unknownJSON := []byte(`{"code":"foo","error":"bar"}`) if res, err := usererrors.UnmarshalJSON(unknownJSON); err != nil { t.Error(err) } else if res.Code() != "foo" { t.Errorf("code=%q, expected %q", res.Code(), "foo") } else if have := res.Error(); have != "bar" { t.Errorf("error=%q, want %q", have, "bar") } }
// Do sends an API request and returns the API response. The API // response is JSON-decoded and stored in the value pointed to by // v. If a known usererror response is returned, the error will be a // UserError with the correct underlying type. func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) { rv := reflect.ValueOf(v) if !(v == nil || rv.Kind() == reflect.Ptr) { return nil, errors.Errorf("value must be a pointer or nil not %s", reflect.TypeOf(v).String()) } resp, err := c.do(req) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode > 399 { body, err := ioutil.ReadAll(resp.Body) if err != nil { return resp, errors.Annotate(err, "unable to read response body") } uerr, err := usererrors.UnmarshalJSON(body) if err != nil { return resp, errors.Annotate(err, "unable to parse error body") } return resp, uerr } else if resp.StatusCode > 299 || resp.StatusCode < 199 { return resp, errors.Errorf("unexpected status code %d", resp.StatusCode) } if v != nil { if err := json.NewDecoder(resp.Body).Decode(v); err != nil { return resp, errors.Annotate(err, "unable to parse response body") } } return resp, nil }
func TestWrapPanic(t *testing.T) { var buf bytes.Buffer reqlog.SetLogger(stdlog.New(&buf, "", 0)) mux := goji.NewMux() mux.HandleFunc(pat.New("/safe"), func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) }) mux.HandleFunc(pat.New("/panic"), func(w http.ResponseWriter, r *http.Request) { panic("hi there!") }) mux.UseC(respond.WrapPanicC) req, err := http.NewRequest("FOO", "/safe", nil) if err != nil { t.Fatal(err) } rr := httptest.NewRecorder() mux.ServeHTTP(rr, req) if err := apptest.AssertStatus(rr, http.StatusNoContent); err != nil { t.Error(err) } buf.Reset() rr = httptest.NewRecorder() req.URL.Path = "/panic" mux.ServeHTTP(rr, req) if err := apptest.AssertStatus(rr, http.StatusInternalServerError); err != nil { t.Error(err) } t.Log(rr.Body.String()) uerr, err := usererrors.UnmarshalJSON(rr.Body.Bytes()) if err != nil { t.Fatal(err) } _, ok := uerr.(usererrors.InternalFailure) if !ok { t.Errorf("expected an InternalFailure but got %#v", uerr) } t.Log(buf.String()) }