A Simplified Http Client. Its initial codes are cloned from HttpRequest. I have refactored the codes and make it more friendly to programmers. And some bugs are fixed and new features are added.
Major changes include:
- can send any string or bytes in body
- can set a shared client for concurrency
- won't clear setting actively
- ......
You can see the release notes for details.
$ go get github.com/smallnest/goreq
goreq comes from gorequest but it added some new features and fixed some bugs. The initial functions and major functions are from gorequest. Thanks to @parnurzeal and other contributors. Why have I not created pull requests to gorequest and created a new repository? I want to refactor it a lot and add features quickly.
GoReq makes http thing more simple for you, using fluent styles to make http client more awesome. You can control headers, timeout, query parameters, binding response and others in one line:
Before
client := &http.Client{
CheckRedirect: redirectPolicyFunc,
}
req, err := http.NewRequest("GET", "http://example.com", nil)
req.Header.Add("If-None-Match", `W/"wyzzy"`)
resp, err := client.Do(req)
Using GoReq
resp, body, errs := goreq.New().Get("http://example.com").
RedirectPolicy(redirectPolicyFunc).
SetHeader("If-None-Match", `W/"wyzzy"`).
End()
resp, body, err := goreq.New().Get("http://httpbin.org/get").End()
q := `{"Name":"Jerry"}`
resp, _, err := goreq.New().Delete("http://httpbin.org/delete").ContentType("json").SendMapString(q).End()
resp, body, err := goreq.New().Head("http://httpbin.org/headers").SendRawString("hello world").End()
resp, body, err := goreq.New().Post("http://httpbin.org/post").SendRawString("hello world").End()
q := `{"Name":"Jerry"}`
resp, body, err := goreq.New().Put("http://httpbin.org/put").ContentType("json").SendMapString(q).End()
q := `{"Name":"Jerry"}`
resp, body, err := goreq.New().Patch("http://httpbin.org/patch").ContentType("json").SendMapString(q).End()
You can set one Header by:
or set some headers by json:
or set some headers by struct:
In the case when you are behind proxy, GoRequest can handle it easily with Proxy func:
request := goreq.New().Proxy("http://proxy:999")
resp, body, errs := request.Get("http://example-proxy.com").End()
Socks5 will be supported in future.
Timeout can be set in any time duration using time package:
request := goreq.New().Timeout(2*time.Millisecond)
resp, body, errs:= request.Get("http://example.com").End()
Timeout func defines both dial + read/write timeout to the specified time parameter.
To add a basic authentication header:
request := goreq.New().SetBasicAuth("username", "password") resp, body, errs := request.Get("http://example-proxy.com").End(.End())
Query function accepts either json string or query strings which will form a query-string in url of GET method or body of POST method. For example, making "/search?query=bicycle&size=50x50&weight=20kg" using GET method:
goreq.New().
Get("/search").
Query(`{ "query": "bicycle" }`).
Query(`{ "size": "50x50" }`).
Query(`{ "weight": "20kg" }`).
End()
It also support query string:
goreq.New().
Get("/search").
Query("query=bicycle&size=50x50").
Query("weight=20kg").
End()
even you can pass a struct:
qq := struct {
Query1 string `json:"query1"`
Query2 string `json:"query2"`
}{
Query1: "test1",
Query2: "test2",
}
goreq.New().
Get("/search").
Query(qq).
End()
Param
can be used to set query value that contains ";" like fields=f1;f2;f3
For POST, PUT, PATCH, you can set content of request BODY.. It is convenient to BODY content.
You can use SendMapString
or SendStruct
to set JSON content. You should set content type to "application/json" by:
goreq.New().Post("/user").ContentType("json")
or
goreq.New().Post("/user").SetHeader("application/json")
GoReq will parse struct, json string or query string and rebuild the json content:
type BrowserVersionSupport struct {
Chrome string
Firefox string
}
ver := BrowserVersionSupport{ Chrome: "37.0.2041.6", Firefox: "30.0" }
goreq.New().
Post("/update_version").
SendStruct(ver).
SendStruct(`{"Safari":"5.1.10"}`).
End()
or
goreq.New().
Post("/search").
SendMapString("query=bicycle&size=50x50").
SendMapString(`{ "wheel": "4"}`).
End()
If you set Content-Type as "application/x-www-form-urlencoded", GoReq rebuilds the below data into form style:
goreq.New().
Post("/search").
ContentType("form").
SendMapString("query=bicycle&size=50x50").
SendMapString(`{ "wheel": "4"}`).
End()
If you want upload XML or other plain text, you can use this method:
goreq.New().
Post("/search").
ContentType("text").
SendRawString("hello world").
End()
Even you can upload raw bytes:
goreq.New().
Post("/search").
ContentType("stream").
SendRawBytes([]byte("hello world")).
End()
You can bind response body to a struct:
type Person struct {
Name string
}
var friend Person
_, _, err := goreq.New().Get(ts.URL).
BindBody(&friend).
End()
GoReqalso supports callback function to handle response:
func printStatus(resp goreq.Response, body string, errs []error){
fmt.Println(resp.Status)
}
goreq.New().Get("http://example.com").End(printStatus)
For deugging, GoReq leverages httputil to dump details of every request/response. You can just use SetDebug to enable/disable debug mode and SetLogger to set your own choice of logger.
For concurrency, you can use a shared client in multiple GoReq instances:
sa := New().Get(ts.URL + case1_empty)
sa.End()
client := sa.Client;
goreq.New().Get(ts.URL+case2_set_header).
SetHeader("API-Key", "fookey").
SetClient(client).
End()
You can reset GoReq and use it send another request. It only keep the client and reset other fields.
goreq.New().Get("http://example.com").Reset()
You can set a retry value and GoReq will retry until the value if it fails. So goreq sends request at most retry + 1 times.
_, _, err := New().Get(ts.URL).
Retry(3, 100, nil).
End()
goreq is MIT License.