// RAINBOND, Application Management Platform // Copyright (C) 2014-2017 Goodrain Co., Ltd. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. For any non-GPL usage of Rainbond, // one or multiple Commercial Licenses authorized by Goodrain Co., Ltd. // must be obtained first. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see . package registry import ( "fmt" "io/ioutil" "net/http" ) type HttpStatusError struct { Response *http.Response Body []byte // Copied from `Response.Body` to avoid problems with unclosed bodies later. Nobody calls `err.Response.Body.Close()`, ever. } func (err *HttpStatusError) Error() string { return fmt.Sprintf("http: non-successful response (status=%v body=%q)", err.Response.StatusCode, err.Body) } var _ error = &HttpStatusError{} type ErrorTransport struct { Transport http.RoundTripper } func (t *ErrorTransport) RoundTrip(request *http.Request) (*http.Response, error) { resp, err := t.Transport.RoundTrip(request) if err != nil { return resp, err } if resp.StatusCode >= 400 { defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("http: failed to read response body (status=%v, err=%q)", resp.StatusCode, err) } return nil, &HttpStatusError{ Response: resp, Body: body, } } return resp, err }