An elegant and simple HTTP client package, which learned a lot from the well-known Python package Requests: HTTP for Humans™.
Brad Fitzpatrick, long time maintainer of the net/http package, wrote Problems with the net/http Client API. The four main points are:
- Too easy to not call Response.Body.Close.
- Too easy to not check return status codes
- Context support is oddly bolted on
- Proper usage is too many lines of boilerplate
requests solves these issues by:
- always closing the response body,
- checking status codes by default,
- optional
context.Context
parameter, - and simplifying the boilerplate.
- Keep-Alive & Connection Pooling
- International Domains and URLs
- Sessions with Cookie Persistence
- Browser-style SSL Verification
- Automatic Content Decoding
- Basic/Digest Authentication
- Elegant Key/Value Cookies
- Automatic Decompression
- Unicode Response Bodies
- HTTP(S) Proxy Support
- Multipart File Uploads
- Streaming Downloads
- Connection Timeouts
- Chunked Requests
- .netrc Support
-
context.Context
Support - Interceptor Support
code with net/http | code with requests |
---|---|
req, err := http.NewRequestWithContext(
ctx, http.MethodGet,
"http://example.com", nil)
if err != nil {
// ...
}
res, err := http.DefaultClient.Do(req)
if err != nil {
// ...
}
defer res.Body.Close()
b, err := io.ReadAll(res.Body)
if err != nil {
// ...
}
s := string(b) |
var txt string
r, err := requests.Get("http://example.com",
requests.ToText(&txt))
if err != nil {
// ...
} |
14+ lines | 4+ lines |
code with net/http | code with requests |
---|---|
body := bytes.NewReader(([]byte(`hello, world`))
req, err := http.NewRequestWithContext(
ctx, http.MethodPost,
"http://example.com", body)
if err != nil {
// ...
}
req.Header.Set("Content-Type", "text/plain")
res, err := http.DefaultClient.Do(req)
if err != nil {
// ...
}
defer res.Body.Close()
_, err := io.ReadAll(res.Body)
if err != nil {
// ...
} |
r, err := requests.Post("http://example.com",
requests.Data(`hello, world`))
if err != nil {
// ...
} |
15+ lines | 4+ lines |
code with net/http | code with requests |
---|---|
u, err := url.Parse("http://example.com")
if err != nil {
// ...
}
req, err := http.NewRequestWithContext(
ctx, http.MethodGet,
u.String(), nil)
if err != nil {
// ...
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
// ...
}
defer resp.Body.Close()
b, err := io.ReadAll(res.Body)
if err != nil {
// ...
}
var res JSONResponse
err := json.Unmarshal(b, &res)
if err != nil {
// ...
} |
var res JSONResponse
r, err := requests.Post("http://example.com",
requests.Context(ctx),
requests.ToJSON(&res))
if err != nil {
// ...
} |
22+ lines | 5+ lines |
req := JSONRequest{
Title: "foo",
Body: "baz",
UserID: 1,
}
var res JSONResponse
r, err := requests.Post("http://example.com",
requests.JSON(&req),
requests.ToJSON(&res))
// Set headers and forms
r, err := requests.Post("http://example.com",
requests.HeaderPairs("martini", "shaken"),
requests.FormPairs("name", "Jacky"))
// Set parameters
r, err := requests.Get("http://example.com?a=1&b=2",
requests.ParamPairs("c", "3"))
// URL: http://example.com?a=1&b=2&c=3
var reqDump, respDump string
r, err := requests.Get("http://example.com",
requests.Dump(&reqDump, &respDump))