Skip to content

wenchy/requests

Repository files navigation

requests

GoDoc Go Report Card Coverage Status License

An elegant and simple HTTP client package, which learned a lot from the well-known Python package Requests: HTTP for Humans™.

Why not just use the standard library HTTP client?

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.

Features

  • 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

Examples

Simple GET a text

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+ lines4+ lines

POST a raw body

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+ lines4+ lines

GET a JSON object with context

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+ lines5+ lines

POST a JSON object and parse the response

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 custom header and form for a request

// Set headers and forms
r, err := requests.Post("http://example.com", 
            requests.HeaderPairs("martini", "shaken"),
            requests.FormPairs("name", "Jacky"))

Easily manipulate URLs and query parameters

// 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

Dump request and response

var reqDump, respDump string
r, err := requests.Get("http://example.com", 
            requests.Dump(&reqDump, &respDump))