Skip to content

Commit

Permalink
fix: better handling of HTTP errors
Browse files Browse the repository at this point in the history
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
  • Loading branch information
CarstenLeue committed Jan 20, 2024
1 parent 89c3425 commit 5a9f405
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
2 changes: 1 addition & 1 deletion http/form/form.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ var (

noField = O.None[string]()

// FormMonoid is the [M.Monoid] for the [Endomorphism]
// Monoid is the [M.Monoid] for the [Endomorphism]
Monoid = ENDO.Monoid[url.Values]()

// ValuesMonoid is a [M.Monoid] to concatenate [url.Values] maps
Expand Down
42 changes: 41 additions & 1 deletion http/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"io"
"mime"
H "net/http"
"net/url"
"regexp"

A "github.com/IBM/fp-go/array"
Expand All @@ -33,6 +34,13 @@ import (

type (
ParsedMediaType = T.Tuple2[string, map[string]string]

HttpError struct {
statusCode int
headers H.Header
body []byte
url *url.URL
}
)

var (
Expand Down Expand Up @@ -72,6 +80,31 @@ func ParseMediaType(mediaType string) E.Either[error, ParsedMediaType] {
return E.TryCatchError(T.MakeTuple2(m, p), err)
}

// Error fulfills the error interface
func (r *HttpError) Error() string {
return fmt.Sprintf("invalid status code [%d] when accessing URL [%s]", r.statusCode, r.url)
}

func (r *HttpError) String() string {
return r.Error()
}

func (r *HttpError) StatusCode() int {
return r.statusCode
}

func (r *HttpError) Headers() H.Header {
return r.headers
}

func (r *HttpError) URL() *url.URL {
return r.url
}

func (r *HttpError) Body() []byte {
return r.body
}

func GetHeader(resp *H.Response) H.Header {
return resp.Header
}
Expand All @@ -84,6 +117,13 @@ func isValidStatus(resp *H.Response) bool {
return resp.StatusCode >= H.StatusOK && resp.StatusCode < H.StatusMultipleChoices
}

// StatusCodeError creates an instance of [HttpError] filled with information from the response
func StatusCodeError(resp *H.Response) error {
return fmt.Errorf("invalid status code [%d] when accessing URL [%s]", resp.StatusCode, resp.Request.URL)
// read the body
bodyRdr := GetBody(resp)
defer bodyRdr.Close()
// try to access body content
body, _ := io.ReadAll(bodyRdr)
// return an error with comprehensive information
return &HttpError{statusCode: resp.StatusCode, headers: GetHeader(resp).Clone(), body: body, url: resp.Request.URL}
}

0 comments on commit 5a9f405

Please sign in to comment.