Created
December 31, 2022 21:16
-
-
Save xeoncross/7f9b3bfc55feef3410888c9381b210f9 to your computer and use it in GitHub Desktop.
Making a HTTP request in Go requires you check multiple things if you want to be safe. Below is an example of something that takes, timeouts, context deadlines, HTTP status codes, and a size limit on the response.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package safehttp | |
// HttpGetRequest assumes the response fits in memory and you're not trying to | |
// decode a json payload which would be better using json.NewDecoder() | |
func HttpGetRequest(ctx context.Context, url string, timeout time.Duration, sizeLimit int64) ([]byte, error) { | |
// Create a new HTTP client with a timeout | |
client := http.Client{Timeout: timeout} | |
req, err := http.NewRequest("GET", url, nil) | |
if err != nil { | |
return nil, err | |
} | |
// Also respect the context deadline | |
req = req.WithContext(ctx) | |
res, err := client.Do(req) | |
if err != nil { | |
return nil, err | |
} | |
defer res.Body.Close() | |
// Assumes a well-behaved (trustable?) server | |
if res.StatusCode < 200 || res.StatusCode > 299 { | |
return nil, fmt.Errorf("unexpected status: got %v", res.Status) | |
} | |
// set sane defaults on expected payload size | |
r := http.MaxBytesReader(nil, res.Body, sizeLimit) | |
// Read the response body | |
body, err := ioutil.ReadAll(r) | |
if err != nil { | |
return nil, fmt.Errorf("error reading response body: %w", err) | |
} | |
// If reading JSON, we would do this instead | |
// t := new(T) | |
// if err := json.NewDecoder(res.Body).Decode(t); err != nil { | |
// return nil, err | |
// } | |
// return t, nil | |
return body, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment