Archived
1
0

Preserve HTTP staus codes in errors if possible

Dropbox being a REST driven service often returns useful information
in the HTTP error code.  Make sure we return these in a custom Error
type if possible.
This commit is contained in:
Nick Craig-Wood 2014-07-13 10:27:02 +01:00
parent 8022b93829
commit 8f46d993e2

View File

@ -231,6 +231,31 @@ func (db *Dropbox) Auth() error {
return err return err
} }
// Error - all errors generated by HTTP transactions are of this type.
// Other error may be passed on from library functions though.
type Error struct {
StatusCode int // HTTP status code
Text string
}
// Error satisfy the error interface.
func (e *Error) Error() string {
return e.Text
}
// newError make a new error from a string.
func newError(StatusCode int, Text string) *Error {
return &Error{
StatusCode: StatusCode,
Text: Text,
}
}
// newErrorf makes a new error from sprintf parameters.
func newErrorf(StatusCode int, Text string, Parameters ...interface{}) *Error {
return newError(StatusCode, fmt.Sprintf(Text, Parameters...))
}
func getResponse(r *http.Response) ([]byte, error) { func getResponse(r *http.Response) ([]byte, error) {
var e requestError var e requestError
var b []byte var b []byte
@ -245,17 +270,17 @@ func getResponse(r *http.Response) ([]byte, error) {
if err = json.Unmarshal(b, &e); err == nil { if err = json.Unmarshal(b, &e); err == nil {
switch v := e.Error.(type) { switch v := e.Error.(type) {
case string: case string:
return nil, fmt.Errorf("%s", v) return nil, newErrorf(r.StatusCode, "%s", v)
case map[string]interface{}: case map[string]interface{}:
for param, reason := range v { for param, reason := range v {
if reasonstr, ok := reason.(string); ok { if reasonstr, ok := reason.(string); ok {
return nil, fmt.Errorf("%s: %s", param, reasonstr) return nil, newErrorf(r.StatusCode, "%s: %s", param, reasonstr)
} }
} }
return nil, fmt.Errorf("wrong parameter") return nil, newErrorf(r.StatusCode, "wrong parameter")
} }
} }
return nil, fmt.Errorf("unexpected HTTP status code %d", r.StatusCode) return nil, newErrorf(r.StatusCode, "unexpected HTTP status code %d")
} }
// CommitChunkedUpload ends the chunked upload by giving a name to the UploadID. // CommitChunkedUpload ends the chunked upload by giving a name to the UploadID.
@ -435,7 +460,7 @@ func (db *Dropbox) Thumbnails(src, format, size string) (io.ReadCloser, int64, *
return nil, 0, nil, os.ErrNotExist return nil, 0, nil, os.ErrNotExist
case http.StatusUnsupportedMediaType: case http.StatusUnsupportedMediaType:
response.Body.Close() response.Body.Close()
return nil, 0, nil, fmt.Errorf("the image located at '%s' cannot be converted to a thumbnail", src) return nil, 0, nil, newErrorf(response.StatusCode, "the image located at '%s' cannot be converted to a thumbnail", src)
} }
json.Unmarshal([]byte(response.Header.Get("x-dropbox-metadata")), &entry) json.Unmarshal([]byte(response.Header.Get("x-dropbox-metadata")), &entry)
return response.Body, response.ContentLength, &entry, err return response.Body, response.ContentLength, &entry, err