googlephotos,onedrive: fix crash on error response - fixes #3491

This fixes a crash on the google photos backend when an error is
returned from the rest.Call function.

This turned out to be a mis-understanding of the rest docs so
- improved rest.Call docs
- fixed mis-understanding in google photos backend
- fixed similar mis-understading in onedrive backend
This commit is contained in:
Nick Craig-Wood 2019-08-28 11:21:38 +01:00
parent 7211c2dca7
commit 0edbc9578d
3 changed files with 17 additions and 14 deletions

View File

@ -956,7 +956,6 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
err = o.fs.pacer.CallNoRetry(func() (bool, error) { err = o.fs.pacer.CallNoRetry(func() (bool, error) {
resp, err = o.fs.srv.Call(&opts) resp, err = o.fs.srv.Call(&opts)
if err != nil { if err != nil {
_ = resp.Body.Close()
return shouldRetry(resp, err) return shouldRetry(resp, err)
} }
token, err = rest.ReadBody(resp) token, err = rest.ReadBody(resp)

View File

@ -1464,22 +1464,24 @@ func (o *Object) uploadFragment(url string, start int64, totalSize int64, chunk
} }
// var response api.UploadFragmentResponse // var response api.UploadFragmentResponse
var resp *http.Response var resp *http.Response
var body []byte
err = o.fs.pacer.Call(func() (bool, error) { err = o.fs.pacer.Call(func() (bool, error) {
_, _ = chunk.Seek(0, io.SeekStart) _, _ = chunk.Seek(0, io.SeekStart)
resp, err = o.fs.srv.Call(&opts) resp, err = o.fs.srv.Call(&opts)
if resp != nil { if err != nil {
defer fs.CheckClose(resp.Body, &err) return shouldRetry(resp, err)
} }
retry, err := shouldRetry(resp, err) body, err = rest.ReadBody(resp)
if !retry && resp != nil { if err != nil {
if resp.StatusCode == 200 || resp.StatusCode == 201 { return shouldRetry(resp, err)
// we are done :)
// read the item
info = &api.Item{}
return false, json.NewDecoder(resp.Body).Decode(info)
}
} }
return retry, err if resp.StatusCode == 200 || resp.StatusCode == 201 {
// we are done :)
// read the item
info = &api.Item{}
return false, json.Unmarshal(body, info)
}
return false, nil
}) })
return info, err return info, err
} }

View File

@ -46,7 +46,7 @@ func ReadBody(resp *http.Response) (result []byte, err error) {
} }
// defaultErrorHandler doesn't attempt to parse the http body, just // defaultErrorHandler doesn't attempt to parse the http body, just
// returns it in the error message // returns it in the error message closing resp.Body
func defaultErrorHandler(resp *http.Response) (err error) { func defaultErrorHandler(resp *http.Response) (err error) {
body, err := ReadBody(resp) body, err := ReadBody(resp)
if err != nil { if err != nil {
@ -178,9 +178,11 @@ func ClientWithNoRedirects(c *http.Client) *http.Client {
// Call makes the call and returns the http.Response // Call makes the call and returns the http.Response
// //
// if err != nil then resp.Body will need to be closed unless // if err == nil then resp.Body will need to be closed unless
// opt.NoResponse is set // opt.NoResponse is set
// //
// if err != nil then resp.Body will have been closed
//
// it will return resp if at all possible, even if err is set // it will return resp if at all possible, even if err is set
func (api *Client) Call(opts *Opts) (resp *http.Response, err error) { func (api *Client) Call(opts *Opts) (resp *http.Response, err error) {
api.mu.RLock() api.mu.RLock()