Skip to content

Commit

Permalink
新增SetTimeout全局配置 (#276)
Browse files Browse the repository at this point in the history
* 新增SetTimeout全局配置

* 加一些测试用例

* 更新测试代码
  • Loading branch information
guonaihong authored Mar 26, 2021
1 parent 3c36f92 commit 380ca7d
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 25 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ gout 是go写的http 客户端,为提高工作效率而开发
- [Incoming custom * http.Client](#Incoming-custom-*http.Client)
- [Global configuration](#Global-configuration)
- [Null values are also serialized](#Null-values-are-also-serialized)
- [Global set timeout](#global-set-timeout)
- [Unique features](#Unique-features)
- [forward gin data](#forward-gin-data)

Expand Down Expand Up @@ -1604,6 +1605,27 @@ gout.GET(url).Debug(true).SetQuery(query).SetHeader(header).BindBody(&body).Do()
```
默认会删除,```authid```等空值,使用gout.NotIgnoreEmpty()接口,空value不会删除

## global set timeout

设置全局超时时间。可以简化一些代码。在使用全局配置默认你已经了解它会带来的一些弊端.
```go
package main
import (
"fmt"
"github.com/guonaihong/gout"
"time"
)
func main() {
gout.SetTimeout(time.Second * 1)
err := gout.GET("www.baidu.com").Do()
if err != nil {
fmt.Printf("err is:%v\n")
}
}
```

# Unique features
## forward gin data
Expand Down
9 changes: 4 additions & 5 deletions dataflow/dataflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ func (df *DataFlow) BindJSON(obj interface{}) *DataFlow {
df.out.opt.RspBodyType = "json"
df.Req.bodyDecoder = decode.NewJSONDecode(obj)
return df

}

// BindYAML parse the yaml string in http body to obj.
Expand Down Expand Up @@ -329,16 +330,14 @@ func (df *DataFlow) Callback(cb func(*Context) error) *DataFlow {

// SetTimeout set timeout, and WithContext are mutually exclusive functions
func (df *DataFlow) SetTimeout(d time.Duration) *DataFlow {
df.Req.index++
df.Req.timeoutIndex = df.Req.index
df.Req.timeout = d
df.Req.SetTimeout(d)
return df
}

// WithContext set context, and SetTimeout are mutually exclusive functions
func (df *DataFlow) WithContext(c context.Context) *DataFlow {
df.Req.index++
df.Req.ctxIndex = df.Req.index
df.Req.Index++
df.Req.ctxIndex = df.Req.Index
df.Req.c = c
return df
}
Expand Down
30 changes: 13 additions & 17 deletions dataflow/req.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import (
"bytes"
"context"
"fmt"
"github.com/guonaihong/gout/core"
"github.com/guonaihong/gout/decode"
"github.com/guonaihong/gout/encode"
api "github.com/guonaihong/gout/interface"
"github.com/guonaihong/gout/setting"
"io"
"io/ioutil"
"net/http"
"net/url"
"reflect"
"strings"
"time"

"github.com/guonaihong/gout/core"
"github.com/guonaihong/gout/decode"
"github.com/guonaihong/gout/encode"
api "github.com/guonaihong/gout/interface"
"github.com/guonaihong/gout/setting"
)

type Do interface {
Expand Down Expand Up @@ -50,19 +50,15 @@ type Req struct {
//cookie
cookies []*http.Cookie

timeout time.Duration

//自增id,主要给互斥API定优先级
//对于互斥api,后面的会覆盖前面的
index int
timeoutIndex int
ctxIndex int
ctxIndex int

c context.Context
Err error

reqModify []api.RequestMiddler
req *http.Request

// 内嵌字段
setting.Setting
}

Expand All @@ -72,8 +68,7 @@ type Req struct {
// headerDecode只有一个可能,就定义为具体类型。这里他们的decode实现也不一样
// 有没有必要,归一化成一种??? TODO:
func (r *Req) Reset() {
r.index = 0
r.NoAutoContentType = false
r.Setting.Reset()
r.Err = nil
r.cookies = nil
r.form = nil
Expand Down Expand Up @@ -348,9 +343,10 @@ func clearHeader(header http.Header) {
}
}

// retry模块需要context.Context,所以这里也返回context.Context
func (r *Req) GetContext() context.Context {
if r.timeout > 0 && r.timeoutIndex > r.ctxIndex {
r.c, _ = context.WithTimeout(context.Background(), r.timeout)
if r.Timeout > 0 && r.TimeoutIndex > r.ctxIndex {
r.c, _ = context.WithTimeout(context.Background(), r.Timeout)
}
return r.c
}
Expand Down
11 changes: 10 additions & 1 deletion gout.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package gout

import (
"net/http"
"time"

"github.com/guonaihong/gout/dataflow"
_ "github.com/guonaihong/gout/export"
_ "github.com/guonaihong/gout/filter"
"net/http"
)

// debug
Expand Down Expand Up @@ -71,3 +73,10 @@ func NotIgnoreEmpty() {
func IgnoreEmpty() {
dataflow.GlobalSetting.NotIgnoreEmpty = false
}

// 设置超时时间,
// d > 0, 设置timeout
// d == 0,取消全局变量
func SetTimeout(d time.Duration) {
dataflow.GlobalSetting.SetTimeout(d)
}
31 changes: 30 additions & 1 deletion setting/setting.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,37 @@
package setting

import "time"

// 设置
type Setting struct {
NotIgnoreEmpty bool //控制是否使用空值
// 控制是否使用空值
NotIgnoreEmpty bool

//是否自动加ContentType
NoAutoContentType bool

//超时时间
Timeout time.Duration

// 目前用作SetTimeout 和 WithContext是互斥
// index是自增id,主要给互斥API定优先级
// 对于互斥api,后面的会覆盖前面的
Index int

//当前time 的index
TimeoutIndex int
}

func (s *Setting) SetTimeout(d time.Duration) {
s.Index++
s.TimeoutIndex = s.Index
s.Timeout = d
}

func (s *Setting) Reset() {
s.NotIgnoreEmpty = false
s.NoAutoContentType = false
s.Index = 0
//s.TimeoutIndex = 0
s.Timeout = time.Duration(0)
}
61 changes: 61 additions & 0 deletions timeout_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package gout

import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
)

func setupDataFlow(t *testing.T) *gin.Engine {
router := gin.New()

router.GET("/timeout", func(c *gin.Context) {
ctx := c.Request.Context()
select {
case <-ctx.Done():
fmt.Printf("setTimeout done\n")
case <-time.After(2 * time.Second):
assert.Fail(t, "test timeout fail")
}
})

return router
}

func Test_Global_Timeout(t *testing.T) {
router := setupDataFlow(t)

const (
longTimeout = 400
middleTimeout = 300
shortTimeout = 200
)

ts := httptest.NewServer(http.HandlerFunc(router.ServeHTTP))
defer ts.Close()

// 只设置timeout
SetTimeout(shortTimeout * time.Millisecond) //设置全局超时时间
err := GET(ts.URL + "/timeout").Do()
assert.Error(t, err)

// 使用互斥api的原则,后面的覆盖前面的
// 这里是WithContext生效, 超时时间400ms
ctx, _ := context.WithTimeout(context.Background(), longTimeout*time.Millisecond)
s := time.Now()
SetTimeout(shortTimeout * time.Millisecond) // 设置全局超时时间
err = GET(ts.URL + "/timeout").
WithContext(ctx).
Do()

assert.Error(t, err)
assert.GreaterOrEqual(t, int(time.Now().Sub(s)), int(middleTimeout*time.Millisecond))

SetTimeout(time.Duration(0))
}
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gout

// Version show version
const Version = "v0.1.5"
const Version = "v0.1.7"

0 comments on commit 380ca7d

Please sign in to comment.