github.com/go-kivik/kivik/v4@v4.3.2/couchdb/chttp/errors.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 2 // use this file except in compliance with the License. You may obtain a copy of 3 // the License at 4 // 5 // http://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 // License for the specific language governing permissions and limitations under 11 // the License. 12 13 package chttp 14 15 import ( 16 "encoding/json" 17 "fmt" 18 "mime" 19 "net/http" 20 ) 21 22 // HTTPError is an error that represents an HTTP transport error. 23 type HTTPError struct { 24 // Response is the HTTP response received by the client. The response body 25 // should already be closed, but the response and request headers and other 26 // metadata will typically be in tact for debugging purposes. 27 Response *http.Response `json:"-"` 28 29 // Reason is the server-supplied error reason. 30 Reason string `json:"reason"` 31 } 32 33 func (e *HTTPError) Error() string { 34 if e.Reason == "" { 35 return http.StatusText(e.HTTPStatus()) 36 } 37 if statusText := http.StatusText(e.HTTPStatus()); statusText != "" { 38 return fmt.Sprintf("%s: %s", statusText, e.Reason) 39 } 40 return e.Reason 41 } 42 43 // HTTPStatus returns the embedded status code. 44 func (e *HTTPError) HTTPStatus() int { 45 return e.Response.StatusCode 46 } 47 48 // ResponseError returns an error from an *http.Response if the status code 49 // indicates an error. 50 func ResponseError(resp *http.Response) error { 51 if resp.StatusCode < 400 { // nolint:gomnd 52 return nil 53 } 54 if resp.Body != nil { 55 defer CloseBody(resp.Body) 56 } 57 httpErr := &HTTPError{ 58 Response: resp, 59 } 60 if resp != nil && resp.Request != nil && resp.Request.Method != "HEAD" && resp.ContentLength != 0 { 61 if ct, _, _ := mime.ParseMediaType(resp.Header.Get("Content-Type")); ct == typeJSON { 62 _ = json.NewDecoder(resp.Body).Decode(httpErr) 63 } 64 } 65 return httpErr 66 }