-
-
Notifications
You must be signed in to change notification settings - Fork 5
ghttp
tony9527167 edited this page Aug 3, 2025
·
4 revisions
设计之初对内置 net/http 包简单封装,为了支持链式调用(Method Chaining)和设置 HTTP 连接超时简单,后续加上 golang/mock 支持。
mock 示例见 https://github.com/giant-stone/go/blob/master/ghttp/ghttp_test.go#L15
const (
DefaultTimeoutInSecs = time.Second * 5
)
func ExampleNew() {
glogging.Install([]string{"stderr"}, "debug", "")
fullurl := "https://httpbin.org/post"
postData := []byte(`{"msg":"hello"}`)
req := ghttp.New().
SetRandomUserAgent(true).
SetTimeout(time.Second * 3).
SetRequestMethod("POST").
SetUri(fullurl).
SetProxy(os.Getenv("HTTPS_PROXY")).
SetPostBody(postData)
err := req.Send()
ghttp.CheckRequestErr(fullurl, req.RespStatus, req.RespBody, err)
fmt.Println(req.RespStatus)
// Output: 200
}
application/x-www-form-urlencoded POST 方式
type FieldForm struct {
Id string
Name string
}
type Rs struct {
Form *FieldForm `json:"form"`
}
// ExampleHttpRequest_SetPostBody show howto POST in application/x-www-form-urlencoded
func ExampleHttpRequest_SetPostBody() {
glogging.Install([]string{"stderr"}, "debug", "")
rq := ghttp.New().
SetRequestMethod("POST").
SetUri("https://httpbin.org/post").
SetTimeout(time.Second * 5)
form := url.Values{}
form.Add("id", fmt.Sprintf("%d", 123))
form.Add("name", "foo")
rq.SetHeader("Content-Type", "application/x-www-form-urlencoded")
rqBody := []byte(form.Encode())
rq.SetPostBody(rqBody)
err := rq.Send()
gutil.ExitOnErr(err)
want := &FieldForm{
Id: form.Get("id"),
Name: form.Get("name"),
}
var rs Rs
err = json.Unmarshal(rq.RespBody, &rs)
gutil.ExitOnErr(err)
fmt.Println(rq.RespStatus)
fmt.Println(want.Id == rs.Form.Id && want.Name == rs.Form.Name)
// Output:
// 200
// true
}
multipart/form-data POST 方式
// ExampleHttpRequest_SetPostBody show howto POST in multipart/form-data
func ExampleHttpRequest_SetPostBody_multipart() {
glogging.Install([]string{"stderr"}, "debug", "")
// use default implement avoid conflict with ghttp/ghttp_test.go
ghttp.UseImpl(nil)
var err error
gh := ghttp.New().SetTimeout(time.Second * 5)
var b bytes.Buffer
w := multipart.NewWriter(&b)
err = ghttp.AppendMultipartFormData(w, "myfile", "myfile.data", []byte(`hello 中文`))
gutil.ExitOnErr(err)
err = ghttp.AppendMultipartFormData(w, "myfile2", "myfile2.data", []byte(`foo\nbar`))
gutil.ExitOnErr(err)
err = w.WriteField("id", "123")
gutil.ExitOnErr(err)
err = w.Close()
gutil.ExitOnErr(err)
rq, err := http.NewRequest("POST", "https://httpbin.org/post", bytes.NewReader(b.Bytes()))
gutil.ExitOnErr(err)
rq.Header.Add("Content-Type", w.FormDataContentType())
rs, err := gh.Do(rq)
gutil.ExitOnErr(err)
rsBody, err := ghttp.ReadBody(rs)
gutil.ExitOnErr(err)
fmt.Println(rs.StatusCode)
fmt.Println(len(rsBody) > 0)
// Output:
// 200
// true
}
func ExampleHttpRequest_DoAndSetPostBody() {
glogging.Install([]string{"stderr"}, "debug", "")
paramsPost := map[string]interface{}{
"msg": "hello",
}
fullurl := "https://httpbin.org/post"
dataPostBody, _ := json.Marshal(paramsPost)
rq := ghttp.New().
SetRequestMethod("POST").
SetUri(fullurl)
rq.SetPostBody(dataPostBody)
resp, err := ghttp.NewWithCtx(context.Background()).
SetTimeout(DefaultTimeoutInSecs).
Do(rq.GenerateRequest())
if err != nil {
log.Fatal(err)
}
dataRsBody, err := ghttp.ReadBody(resp)
if err != nil {
log.Fatal(err)
}
type Rs struct {
Data string
}
rs := &Rs{}
err = json.Unmarshal(dataRsBody, rs)
if err != nil {
log.Fatal(err)
}
ghttp.CheckRequestErr(fullurl, resp.StatusCode, dataRsBody, err)
fmt.Println(resp.StatusCode)
fmt.Println(rs.Data)
// Output: 200
// {"msg":"hello"}
}
func ExampleReadBody() {
glogging.Install([]string{"stderr"}, "error", "")
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
gh := ghttp.NewWithCtx(ctx).SetUri("https://httpbin.org/uuid")
rs, err := gh.Do(gh.GenerateRequest())
if err != nil {
log.Fatal(err)
}
for i := 0; i < 3; i++ {
body, err := ghttp.ReadBody(rs)
if err != nil {
log.Fatal(err)
}
// something looks like `{"uuid": "2ae860ed-47da-4adb-9373-128f3eb4ce71"}`
fmt.Println(len(body))
}
// Output: 53
// 53
// 53
}