Skip to content

Commit

Permalink
Issue343 (#345)
Browse files Browse the repository at this point in the history
* 完成issue

* 新加测试
  • Loading branch information
guonaihong authored Dec 10, 2022
1 parent e7a6777 commit cc27f1a
Show file tree
Hide file tree
Showing 16 changed files with 307 additions and 28 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ gout 是go写的http 客户端,为提高工作效率而开发
- [callback](#callback)
- [get *http.Response](#get-response)
- [multiple binding functions](#multiple-binding-functions)
- [Auto decode body](#auto-decode-body)
- [Set request timeout](#Set-request-timeout)
- [proxy](#proxy)
- [socks5](#socks5)
Expand Down Expand Up @@ -569,7 +570,7 @@ import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/guonaihong/gout"
middler "github.com/guonaihong/gout/interface"
"github.com/guonaihong/gout/middler"
"io/ioutil"
"log"
"net/http"
Expand Down Expand Up @@ -1124,7 +1125,7 @@ func main() {
```
### multiple binding functions
支持绑定多个对象
支持绑定多个对象, BindXXX函数可以多次调用。例子里面是BindJSON和BindBody
```go
var responseStruct struct {
Name string `json:"name"`
Expand All @@ -1147,6 +1148,17 @@ func main() {
log.Println(responseStr)
}
```
### Auto decode body
响应头里面指明压缩格式,使用AutoDecodeBody接口可以自动解压。
```go
//Content-Encoding: gzip
//Content-Encoding: deflate
//Content-Encoding: br
//gzip由标准库原生支持,不需要使用AutoDecodeBody接口,后两种由gout支持.
func main() {
gout.GET(url).AutoDecodeBody().BindBody(&s).Do()
}
```
## Set request timeout
setimeout是request级别的超时方案。相比http.Client级别,更灵活。
Expand Down
13 changes: 10 additions & 3 deletions dataflow/dataflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import (
"github.com/guonaihong/gout/debug"
"github.com/guonaihong/gout/decode"
"github.com/guonaihong/gout/encode"
api "github.com/guonaihong/gout/interface"
"github.com/guonaihong/gout/middler"
"github.com/guonaihong/gout/middleware/rsp/autodecodebody"
"github.com/guonaihong/gout/setting"
"golang.org/x/net/proxy"
)
Expand Down Expand Up @@ -378,15 +379,15 @@ func (df *DataFlow) SetBasicAuth(username, password string) *DataFlow {
}

// Request middleware
func (df *DataFlow) RequestUse(reqModify ...api.RequestMiddler) *DataFlow {
func (df *DataFlow) RequestUse(reqModify ...middler.RequestMiddler) *DataFlow {
if len(reqModify) > 0 {
df.reqModify = append(df.reqModify, reqModify...)
}
return df
}

// Response middleware
func (df *DataFlow) ResponseUse(responseModify ...api.ResponseMiddler) *DataFlow {
func (df *DataFlow) ResponseUse(responseModify ...middler.ResponseMiddler) *DataFlow {
if len(responseModify) > 0 {
df.responseModify = append(df.responseModify, responseModify...)
}
Expand Down Expand Up @@ -420,6 +421,12 @@ func (df *DataFlow) NoAutoContentType() *DataFlow {
return df
}

// https://github.com/guonaihong/gout/issues/343
// content-encoding会指定response body的压缩方法,支持常用的压缩,gzip, deflate, br等
func (df *DataFlow) AutoDecodeBody() *DataFlow {
return df.ResponseUse(middler.WithResponseMiddlerFunc(autodecodebody.AutoDecodeBody))
}

func (df *DataFlow) IsDebug() bool {
return df.Setting.Debug
}
Expand Down
91 changes: 91 additions & 0 deletions dataflow/dataflow_auto_decode_body_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package dataflow

import (
"bytes"
"compress/gzip"
"compress/zlib"
"log"
"net/http"
"net/http/httptest"
"testing"
"time"

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

var test_autoDecodeBody_data = "test auto decode boyd function"

// 测试服务
func create_AutoDecodeBody() *httptest.Server {
r := gin.New()
r.GET("/gzip", func(c *gin.Context) {

var buf bytes.Buffer

zw := gzip.NewWriter(&buf)
// Setting the Header fields is optional.
zw.Name = "a-new-hope.txt"
zw.Comment = "an epic space opera by George Lucas"
zw.ModTime = time.Date(1977, time.May, 25, 0, 0, 0, 0, time.UTC)
_, err := zw.Write([]byte(test_autoDecodeBody_data))
if err != nil {
log.Fatal(err)
}

if err := zw.Close(); err != nil {
log.Fatal(err)
}
c.Header("Content-Encoding", "gzip")
c.String(200, buf.String())
})

r.GET("/br", func(c *gin.Context) {

c.Header("Content-Encoding", "br")
var buf bytes.Buffer
w := brotli.NewWriter(&buf)
w.Write([]byte(test_autoDecodeBody_data))
w.Flush()
w.Close()
c.String(200, buf.String())
})

r.GET("/deflate", func(c *gin.Context) {

var buf bytes.Buffer
w := zlib.NewWriter(&buf)
w.Write([]byte(test_autoDecodeBody_data))
w.Close()
c.Header("Content-Encoding", "deflate")
c.String(200, buf.String())
})

r.GET("/compress", func(c *gin.Context) {
c.Header("Content-Encoding", "compress")
})
return httptest.NewServer(http.HandlerFunc(r.ServeHTTP))
}

func Test_AutoDecodeBody(t *testing.T) {
ts := create_AutoDecodeBody()
var err error
for _, path := range []string{"/gzip", "/br", "/deflate"} {
s := ""
if path == "/gzip" {
err = New().GET(ts.URL + path).Debug(true).BindBody(&s).Do()
} else {
err = New().GET(ts.URL + path).AutoDecodeBody().Debug(true).BindBody(&s).Do()

}
assert.NoError(t, err)
assert.Equal(t, s, test_autoDecodeBody_data)
}
}

func Test_AutoDecodeBody_Fail(t *testing.T) {
ts := create_AutoDecodeBody()
err := New().GET(ts.URL + "/compress").AutoDecodeBody().Do()
assert.Error(t, err)
}
6 changes: 3 additions & 3 deletions dataflow/dataflow_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

core "github.com/guonaihong/gout/core"

api "github.com/guonaihong/gout/interface"
"github.com/guonaihong/gout/middler"
"github.com/stretchr/testify/assert"
)

Expand All @@ -24,7 +24,7 @@ func (d *demoRequestMiddler) ModifyRequest(req *http.Request) error {
return nil
}

func demoRequest() api.RequestMiddler {
func demoRequest() middler.RequestMiddler {
return &demoRequestMiddler{}
}

Expand Down Expand Up @@ -65,7 +65,7 @@ func (d *demoResponseMiddler) ModifyResponse(response *http.Response) error {
return nil
}
}
func demoResponse() api.ResponseMiddler {
func demoResponse() middler.ResponseMiddler {
return &demoResponseMiddler{}
}

Expand Down
6 changes: 3 additions & 3 deletions dataflow/req.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/guonaihong/gout/debug"
"github.com/guonaihong/gout/decode"
"github.com/guonaihong/gout/encode"
api "github.com/guonaihong/gout/interface"
"github.com/guonaihong/gout/middler"
"github.com/guonaihong/gout/setting"
)

Expand Down Expand Up @@ -54,9 +54,9 @@ type Req struct {
c context.Context
Err error

reqModify []api.RequestMiddler
reqModify []middler.RequestMiddler

responseModify []api.ResponseMiddler
responseModify []middler.ResponseMiddler

req *http.Request

Expand Down
4 changes: 2 additions & 2 deletions debug/debug_trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"time"

"github.com/guonaihong/gout/color"
api "github.com/guonaihong/gout/interface"
"github.com/guonaihong/gout/middler"
)

type TraceInfo struct {
Expand All @@ -25,7 +25,7 @@ type TraceInfo struct {
w io.Writer
}

func (t *TraceInfo) StartTrace(opt *Options, needTrace bool, req *http.Request, do api.Do) (*http.Response, error) {
func (t *TraceInfo) StartTrace(opt *Options, needTrace bool, req *http.Request, do middler.Do) (*http.Response, error) {
w := opt.Write
var dnsStart, connStart, reqStart, tlsStart, waitResponseStart, respStart time.Time
var dnsDuration, connDuration, reqDuration, tlsDuration, waitResponeDuration time.Duration
Expand Down
11 changes: 1 addition & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/guonaihong/gout
go 1.18

require (
github.com/andybalholm/brotli v1.0.4
github.com/gin-gonic/gin v1.7.0
github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0
Expand All @@ -19,23 +20,13 @@ require (
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/assert/v2 v2.0.1 // indirect
github.com/golang/protobuf v1.5.0 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/google/gofuzz v1.0.0 // indirect
github.com/json-iterator/go v1.1.9 // indirect
github.com/kisielk/godepgraph v0.0.0-20220719222756-573dc89cecc8 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.1.0 // indirect
github.com/ugorji/go v1.1.7 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
golang.org/x/text v0.3.2 // indirect
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 // indirect
)
5 changes: 2 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -23,8 +25,6 @@ github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/kisielk/godepgraph v0.0.0-20220719222756-573dc89cecc8 h1:4q/BeJpElGXg5jX05HFJEyZxkM/cjQGQvr1FzCBnvRA=
github.com/kisielk/godepgraph v0.0.0-20220719222756-573dc89cecc8/go.mod h1:Gb5YEgxqiSSVrXKWQxDcKoCM94NO5QAwOwTaVmIUAMI=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
Expand All @@ -42,7 +42,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
Expand Down
8 changes: 8 additions & 0 deletions interface/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## 不建议使用这个目录下的代码
建议使用如下目录
```go
github.com/guonaihong/gout/middler
```

## 这个目录的代码将在未来4-5个版本迭代之后删除
请做好迁移 v0.3.1版本开始算起,大约在v0.3.6版本移除
7 changes: 7 additions & 0 deletions middler/do.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package middler

import "net/http"

type Do interface {
Do(*http.Request) (*http.Response, error)
}
19 changes: 19 additions & 0 deletions middler/request_use_interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package middler

import "net/http"

type RequestMiddlerFunc func(req *http.Request) error

type RequestMiddler interface {
ModifyRequest(req *http.Request) error
}

func (f RequestMiddlerFunc) ModifyRequest(req *http.Request) error {
return f(req)
}

// WithRequestMiddlerFunc 是创建一个 RequestMiddler 的helper
// 如果我们只需要简单的逻辑,只关注闭包本身,则可以使用这个helper快速创建一个 RequestMiddler
func WithRequestMiddlerFunc(f RequestMiddlerFunc) RequestMiddler {
return f
}
22 changes: 22 additions & 0 deletions middler/response_use_interface.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package middler

import (
"net/http"
)

type ResponseMiddlerFunc func(response *http.Response) error

// ResponseMiddler 响应拦截器
type ResponseMiddler interface {
ModifyResponse(response *http.Response) error
}

func (f ResponseMiddlerFunc) ModifyResponse(response *http.Response) error {
return f(response)
}

// WithResponseMiddlerFunc 是创建一个 ResponseMiddler 的helper
// 如果我们只需要简单的逻辑,只关注闭包本身,则可以使用这个helper快速创建一个 ResponseMiddler
func WithResponseMiddlerFunc(f ResponseMiddlerFunc) ResponseMiddler {
return f
}
Loading

0 comments on commit cc27f1a

Please sign in to comment.