github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/http/response.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package http 5 6 import ( 7 "encoding/json" 8 "io/ioutil" 9 "net/http" 10 11 "github.com/juju/errors" 12 13 "github.com/juju/juju/apiserver/params" 14 ) 15 16 // ExtractJSONResult unserializes the JSON-encoded result into the 17 // provided struct. 18 func ExtractJSONResult(resp *http.Response, result interface{}) error { 19 // We defer closing the body here because we want it closed whether 20 // or not the subsequent read fails. 21 defer resp.Body.Close() 22 23 if resp.Header.Get("Content-Type") != CTypeJSON { 24 return errors.Errorf(`expected "application/json" content type, got %q`, resp.Header.Get("Content-Type")) 25 } 26 27 err := json.NewDecoder(resp.Body).Decode(result) 28 return errors.Trace(err) 29 } 30 31 // ExtractAPIError returns the failure serialized in the response 32 // body. If there is no failure (an OK status code), it simply returns 33 // nil. 34 func ExtractAPIError(resp *http.Response) (*params.Error, error) { 35 if resp.StatusCode == http.StatusOK { 36 return nil, nil 37 } 38 // We defer closing the body here because we want it closed whether 39 // or not the subsequent read fails. 40 defer resp.Body.Close() 41 42 body, err := ioutil.ReadAll(resp.Body) 43 if err != nil { 44 return nil, errors.Annotate(err, "while reading HTTP response") 45 } 46 47 var failure params.Error 48 if resp.Header.Get("Content-Type") == CTypeJSON { 49 if err := json.Unmarshal(body, &failure); err != nil { 50 return nil, errors.Annotate(err, "while unserializing the error") 51 } 52 } else { 53 switch resp.StatusCode { 54 case http.StatusNotFound, http.StatusMethodNotAllowed: 55 failure.Code = params.CodeNotImplemented 56 default: 57 // Leave Code empty. 58 } 59 60 failure.Message = string(body) 61 } 62 return &failure, nil 63 }