From 20fbe0ae6efb57c3782f221f7212e425f36bc3df Mon Sep 17 00:00:00 2001 From: guonaihong Date: Thu, 3 Jun 2021 22:10:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=BF=BD=E7=95=A5ssl?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=20(#286)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 支持忽略ssl验证, 还差测试代码 * 补全测试代码, 还差文档说明 * 新增文档 --- README.md | 20 ++++++++++ gout_newopt.go | 58 ++++++++++++++++++++++++++++ gout_newopt_test.go | 41 ++++++++++++++++++++ gout_newopt_with_skip_verify_test.go | 51 ++++++++++++++++++++++++ gout_options.go | 42 ++++++++++++++++++++ 5 files changed, 212 insertions(+) create mode 100644 gout_newopt.go create mode 100644 gout_newopt_test.go create mode 100644 gout_newopt_with_skip_verify_test.go create mode 100644 gout_options.go diff --git a/README.md b/README.md index 7e485f9..d1bcb3a 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ gout 是go写的http 客户端,为提高工作效率而开发 - [Incoming custom * http.Client](#Incoming-custom-*http.Client) - [Using chunked data format](#Using-chunked-data-format) - [Global configuration](#Global-configuration) + - [Insecure skip verify](#insecure-skip-verify) - [Null values are also serialized](#Null-values-are-also-serialized) - [Global set timeout](#global-set-timeout) - [Unique features](#Unique-features) @@ -1614,6 +1615,25 @@ func main() { ``` # Global configuration +这里记录全局配置的方法, 后面所有的全局配置都推荐使用```gout.NewWithOpt```接口的实现 +## insecure skip verify +忽略ssl验证, 使用```gout.WithInsecureSkipVerify()```接口配置该功能, 传入```gout.NewWithOpt```接口即可生效. +```go +import ( + "github.com/guonaihong/gout" +) + +func main() { + // globalWithOpt里面包含连接池, 这是一个全局可复用的对象 + globalWithOpt := gout.NewWithOpt(gout.WithInsecureSkipVerify()) + err := globalWithOpt.GET("url").Do() + if err != nil { + fmt.Printf("err = %v\n" ,err) + return + } +} +``` + ## Null values are also serialized ```go query := gout.H{ diff --git a/gout_newopt.go b/gout_newopt.go new file mode 100644 index 0000000..6411df7 --- /dev/null +++ b/gout_newopt.go @@ -0,0 +1,58 @@ +package gout + +import ( + "net/http" + + "github.com/guonaihong/gout/dataflow" +) + +type Client struct { + options +} + +func NewWithOpt(opts ...Option) *Client { + c := &Client{} + c.hc = &http.Client{} + + for _, o := range opts { + o.apply(&c.options) + } + + return c + +} + +// GET send HTTP GET method +func (c *Client) GET(url string) *dataflow.DataFlow { + return dataflow.New(c.hc).GET(url) +} + +// POST send HTTP POST method +func (c *Client) POST(url string) *dataflow.DataFlow { + return dataflow.New(c.hc).POST(url) +} + +// PUT send HTTP PUT method +func (c *Client) PUT(url string) *dataflow.DataFlow { + return dataflow.New(c.hc).PUT(url) +} + +// DELETE send HTTP DELETE method +func (c *Client) DELETE(url string) *dataflow.DataFlow { + return dataflow.New(c.hc).DELETE(url) +} + +// PATCH send HTTP PATCH method +func (c *Client) PATCH(url string) *dataflow.DataFlow { + return dataflow.New(c.hc).PATCH(url) +} + +// HEAD send HTTP HEAD method +func (c *Client) HEAD(url string) *dataflow.DataFlow { + return dataflow.New(c.hc).HEAD(url) +} + +// OPTIONS send HTTP OPTIONS method +func (c *Client) OPTIONS(url string) *dataflow.DataFlow { + return dataflow.New(c.hc).OPTIONS(url) +} diff --git a/gout_newopt_test.go b/gout_newopt_test.go new file mode 100644 index 0000000..095ea95 --- /dev/null +++ b/gout_newopt_test.go @@ -0,0 +1,41 @@ +package gout + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_NewWithOptTopMethod(t *testing.T) { + var total int32 + + router := setupMethod(&total) + + ts := httptest.NewServer(http.HandlerFunc(router.ServeHTTP)) + defer ts.Close() + + err := NewWithOpt().GET(ts.URL + "/someGet").Do() + assert.NoError(t, err) + + err = NewWithOpt().POST(ts.URL + "/somePost").Do() + assert.NoError(t, err) + + err = NewWithOpt().PUT(ts.URL + "/somePut").Do() + assert.NoError(t, err) + + err = NewWithOpt().DELETE(ts.URL + "/someDelete").Do() + assert.NoError(t, err) + + err = NewWithOpt().PATCH(ts.URL + "/somePatch").Do() + assert.NoError(t, err) + + err = NewWithOpt().HEAD(ts.URL + "/someHead").Do() + assert.NoError(t, err) + + err = NewWithOpt().OPTIONS(ts.URL + "/someOptions").Do() + assert.NoError(t, err) + + assert.Equal(t, int(total), 7) +} diff --git a/gout_newopt_with_skip_verify_test.go b/gout_newopt_with_skip_verify_test.go new file mode 100644 index 0000000..34bd276 --- /dev/null +++ b/gout_newopt_with_skip_verify_test.go @@ -0,0 +1,51 @@ +package gout + +import ( + "log" + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" +) + +type chanWriter chan string + +func (w chanWriter) Write(p []byte) (n int, err error) { + w <- string(p) + return len(p), nil +} + +func Test_WithInsecureSkipVerify(t *testing.T) { + + ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Hello")) + })) + + errc := make(chanWriter, 10) // but only expecting 1 + ts.Config.ErrorLog = log.New(errc, "", 0) + + defer ts.Close() + + c := ts.Client() + for _, insecure := range []bool{true, false} { + var opts []Option + if insecure { + opts = []Option{WithClient(c), WithInsecureSkipVerify()} + } + client := NewWithOpt(opts...) + err := client.GET(ts.URL).Do() + if (err == nil) != insecure { + t.Errorf("#insecure=%v: got unexpected err=%v", insecure, err) + } + } + + select { + case v := <-errc: + if !strings.Contains(v, "TLS handshake error") { + t.Errorf("expected an error log message containing 'TLS handshake error'; got %q", v) + } + case <-time.After(5 * time.Second): + t.Errorf("timeout waiting for logged error") + } +} diff --git a/gout_options.go b/gout_options.go new file mode 100644 index 0000000..22d4fb4 --- /dev/null +++ b/gout_options.go @@ -0,0 +1,42 @@ +package gout + +import ( + "crypto/tls" + "net/http" +) + +type options struct { + hc *http.Client +} + +type Option interface { + apply(*options) +} + +type insecureSkipVerifyOption bool + +func (i insecureSkipVerifyOption) apply(opts *options) { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + } + + opts.hc.Transport = tr +} + +// 忽略ssl验证 +func WithInsecureSkipVerify() Option { + b := true + return insecureSkipVerifyOption(b) +} + +type client http.Client + +func (c *client) apply(opts *options) { + opts.hc = (*http.Client)(c) +} + +func WithClient(c *http.Client) Option { + return (*client)(c) +}