11package coder
22
33import (
4+ "bytes"
45 "encoding/json"
56 "fmt"
7+ "io"
68 "net/http"
79
810 "golang.org/x/xerrors"
@@ -29,11 +31,31 @@ type APIErrorMsg struct {
2931 Details json.RawMessage `json:"details"`
3032}
3133
34+ // NewHTTPError reads the response body and stores metadata
35+ // about the response in order to be unpacked into
36+ // an *APIError.
37+ func NewHTTPError (resp * http.Response ) * HTTPError {
38+ var buf bytes.Buffer
39+ _ , err := io .CopyN (& buf , resp .Body , 1 << 6 )
40+ if err != nil {
41+ return & HTTPError {
42+ cachedErr : err ,
43+ }
44+ }
45+ return & HTTPError {
46+ url : resp .Request .URL .String (),
47+ statusCode : resp .StatusCode ,
48+ body : buf .Bytes (),
49+ }
50+ }
51+
3252// HTTPError represents an error from the Coder API.
3353type HTTPError struct {
34- * http.Response
35- cached * APIError
36- cachedErr error
54+ url string
55+ statusCode int
56+ body []byte
57+ cached * APIError
58+ cachedErr error
3759}
3860
3961// Payload decode the response body into the standard error structure. The `details`
@@ -46,7 +68,7 @@ func (e *HTTPError) Payload() (*APIError, error) {
4668
4769 // Try to decode the payload as an error, if it fails or if there is no error message,
4870 // return the response URL with the status.
49- if err := json .NewDecoder (e .Response . Body ). Decode ( & msg ); err != nil {
71+ if err := json .Unmarshal (e .body , & msg ); err != nil {
5072 e .cachedErr = err
5173 return nil , err
5274 }
@@ -55,16 +77,16 @@ func (e *HTTPError) Payload() (*APIError, error) {
5577 return & msg , nil
5678}
5779
80+ func (e * HTTPError ) StatusCode () int {
81+ return e .statusCode
82+ }
83+
5884func (e * HTTPError ) Error () string {
5985 apiErr , err := e .Payload ()
6086 if err != nil || apiErr .Err .Msg == "" {
61- return fmt .Sprintf ("%s: %d %s" , e .Request . URL , e .StatusCode , e . Status )
87+ return fmt .Sprintf ("%s: %d %s" , e .url , e .statusCode , http . StatusText ( e . statusCode ) )
6288 }
6389
6490 // If the payload was a in the expected error format with a message, include it.
6591 return apiErr .Err .Msg
6692}
67-
68- func bodyError (resp * http.Response ) error {
69- return & HTTPError {Response : resp }
70- }
0 commit comments