/sreq

A simple, user-friendly and concurrent safe HTTP request library for Go

Primary LanguageGoMIT LicenseMIT

sreq

A simple, user-friendly and concurrent safe HTTP request library for Go, 's' means simple.

Actions Status Mentioned in Awesome Go codecov Go Report Card GoDoc License

Notes

sreq now is under an alpha test state, its APIs may be changed in future so it's not recommended to use in production. Welcome to give advise to the project.

Features

  • GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, etc.
  • Easy set query params, headers and cookies.
  • Easy send form, JSON or files payload.
  • Easy set basic authentication or bearer token.
  • Automatic cookies management.
  • Customize HTTP client.
  • Easy set context.
  • Easy decode responses, raw data, text representation and unmarshal the JSON-encoded data.
  • Concurrent safe.

Install

go get -u github.com/winterssy/sreq

Usage

import "github.com/winterssy/sreq"

Examples

The usages of sreq are very similar to net/http library, you can switch from it to sreq easily. For example, if your HTTP request code like this:

resp, err := http.Get("http://www.google.com")

Use sreq you just need to change your code like this:

resp, err := sreq.Get("http://www.google.com").Resolve()

See more examples as follow.

Set Query Params

data, err := sreq.
    Get("http://httpbin.org/get",
        sreq.WithQuery(sreq.Params{
            "key1": "value1",
            "key2": "value2",
        }),
       ).
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Set Headers

data, err := sreq.
    Get("http://httpbin.org/get",
        sreq.WithHeaders(sreq.Headers{
            "Origin":  "http://httpbin.org",
            "Referer": "http://httpbin.org",
        }),
       ).
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Set Cookies

data, err := sreq.
    Get("http://httpbin.org/cookies",
        sreq.WithCookies(
            &http.Cookie{
                Name:  "name1",
                Value: "value1",
            },
            &http.Cookie{
                Name:  "name2",
                Value: "value2",
            },
        ),
       ).
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Send Form

data, err := sreq.
    Post("http://httpbin.org/post",
         sreq.WithForm(sreq.Form{
             "key1": "value1",
             "key2": "value2",
         }),
        ).
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Send JSON

data, err := sreq.
    Post("http://httpbin.org/post",
         sreq.WithJSON(sreq.JSON{
             "msg": "hello world",
             "num": 2019,
         }, true),
        ).
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Upload Files

data, err := sreq.
    Post("http://httpbin.org/post",
         sreq.WithFiles(sreq.Files{
             "image1": "./testdata/testimage1.jpg",
             "image2": "./testdata/testimage2.jpg",
         }),
        ).
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Set Basic Authentication

data, err := sreq.
    Get("http://httpbin.org/basic-auth/admin/pass",
        sreq.WithBasicAuth("admin", "pass"),
       ).
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Set Bearer Token

data, err := sreq.
    Get("http://httpbin.org/bearer",
        sreq.WithBearerToken("sreq"),
       ).
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Set Default HTTP Request Options

If you want to set default HTTP request options for per request, you can do like this:

sreq.SetDefaultRequestOpts(
    sreq.WithQuery(sreq.Params{
        "defaultKey1": "defaultValue1",
        "defaultKey2": "defaultValue2",
    }),
)
data, err := sreq.
    Get("http://httpbin.org/get").
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Customize HTTP Client

For some reasons, sreq does not provide direct APIs for setting transport, redirection policy, cookie jar, timeout, proxy or something else can be set by constructing a *http.Client. Construct a custom sreq client if you want to do so.

transport := &http.Transport{
    Proxy: http.ProxyFromEnvironment,
    DialContext: (&net.Dialer{
        Timeout:   30 * time.Second,
        KeepAlive: 30 * time.Second,
    }).DialContext,
    MaxIdleConns:          100,
    IdleConnTimeout:       90 * time.Second,
    TLSHandshakeTimeout:   10 * time.Second,
    ExpectContinueTimeout: 1 * time.Second,
}
redirectPolicy := func(req *http.Request, via []*http.Request) error {
    return http.ErrUseLastResponse
}
jar, _ := cookiejar.New(&cookiejar.Options{
    PublicSuffixList: publicsuffix.List,
})
timeout := 120 * time.Second

httpClient := &http.Client{
    Transport:     transport,
    CheckRedirect: redirectPolicy,
    Jar:           jar,
    Timeout:       timeout,
}

req := sreq.New(httpClient)
data, err := req.
    Get("http://httpbin.org/get").
    Text()
if err != nil {
    panic(err)
}
fmt.Println(data)

Concurrent Safe

sreq is concurrent safe, you can easily use it across goroutines.

const MaxWorker = 1000
wg := new(sync.WaitGroup)

for i := 0; i < MaxWorker; i++ {
    wg.Add(1)
    go func(i int) {
        defer wg.Done()

        params := sreq.Params{}
        params.Set(fmt.Sprintf("key%d", i), fmt.Sprintf("value%d", i))

        data, err := sreq.
            Get("http://httpbin.org/get",
                sreq.WithQuery(params),
               ).
            Text()
        if err != nil {
            return
        }

        fmt.Println(data)
    }(i)
}

wg.Wait()

License

MIT.