Errors
Tell a transport failure apart from an HTTP error status, and handle failures on a stream.
The client draws a clear line between a request that could not be made and a request that came back with an error status. Knowing which is which is the whole error model.
A returned error means the request failed
A verb returns a non-nil error only when the request could not be built, sent, or read. A failure to join the URL, a refused connection, a canceled context, or a body that could not be read all surface as the returned error, already wrapped with context.
resp, err := client.Get(ctx, http.GetRequest{Request: http.Request{Path: "/users/1"}})
if err != nil {
// the request never completed, a connection, timeout, or malformed URL
return fmt.Errorf("failed to fetch user: %w", err)
}An error status is a normal response
An HTTP status such as 404 or 500 is a completed request, so it comes back as a *Response with a nil error. Check resp.StatusCode yourself and read resp.Body for the server's error payload.
resp, err := client.Get(ctx, http.GetRequest{Request: http.Request{Path: "/users/1"}})
if err != nil {
return err
}
if resp.StatusCode >= 400 {
return fmt.Errorf("user lookup returned %d: %s", resp.StatusCode, resp.Body)
}Note
This split keeps the two kinds of failure from being confused. A transport error is never a valid response, and a 4xx or 5xx is never a Go error, so a caller always knows which one it is handling.
Errors on a stream
A streaming call reports failure in two places. GetStream and PostStream return an error when the initial request fails or comes back with a non-OK status. The same failure, and any read error partway through, also arrives as a final StreamResponseTypeEOF frame whose Error is set.
stream := make(chan http.StreamResponse)
if err := client.GetStream(ctx, stream, http.Request{Path: "/events"}); err != nil {
return err
}
for ev := range stream {
if ev.Type == http.StreamResponseTypeEOF && ev.Error != nil {
return ev.Error
}
// handle ev
}A clean end of stream is a StreamResponseTypeEOF frame with a nil Error. See Streaming for the full frame loop.