diff --git a/README.md b/README.md index 7d19e9f..d8cd6f8 100644 --- a/README.md +++ b/README.md @@ -28,69 +28,89 @@ go get github.com/xfali/restclient ### 基础配置 -请参照DefaultRestClient的API说明 +可以在创建默认client时对其进行配置,支持的options请参照[options](init_opts.go)的API说明 + +使用为 +``` +// restclient.New(Option1, Option2 ... OptionN), 例: +client := restclient.New(restclient.SetTimeout(10*time.Second)) +``` ``` //设置读写超时 -func SetTimeout(timeout time.Duration) +restclient.SetTimeout(timeout time.Duration) ``` ``` //配置初始转换器列表 -func SetConverters(convs []Converter) +restclient.SetConverters(convs []Converter) ``` ``` //配置连接池 -func SetRoundTripper(tripper http.RoundTripper) +restclient.SetRoundTripper(tripper http.RoundTripper) ``` ``` // 增加处理filter -func AddFilter(filters ...Filter) +restclient.AddFilter(filters ...Filter) ``` ``` //配置request创建器 -func SetRequestCreator(f RequestCreator) +restclient.SetRequestCreator(f RequestCreator) +``` +``` +// CookieJar 配置http.Client的CookieJar +restclient.CookieJar(jar http.CookieJar) +``` +``` +// 配置http客户端创建器 +restclient.SetClientCreator(cliCreator HttpClientCreator) ``` ### 连接池配置 -请参照transport的API说明 +请参照http.transport的API说明 ## 使用 - +1. 使用request传递http请求参数 ``` //使用默认配置 client := restclient.New() -str := "" -n, err := c.Get(&str, "https://${ADDRESS}", nil) -n, err := c.Post(&str, "https://${ADDRESS}", - restutil.Headers().WithContentType(MediaTypeJson).Build(), Entity{}) +resp := &Response{} +err := client.Exchange("http://localhost:8080/test", + request.WithResult(&ret), + request.WithResponse(resp, false)) +``` +2. 使用request builder创建和传递http请求参数 +``` +err := client.Exchange("http://localhost:8080/error", + restclient.NewRequest(). + MethodPost(). + RequestBody(req). + Result(&resp). + Build()) ``` ## 扩展 -使用ClientWrapper进行行为控制和扩展功能,如增加client的输入输出日志: -```cassandraql -o := restclient.New(restclient.SetTimeout(time.Second)) -c := restclient.NewWrapper(o, func(ex restclient.Exchange) restclient.Exchange { - return func(result interface{}, url string, method string, params map[string]interface{}, requestBody interface{}) (i int, e error) { - t.Logf("url: %v, method: %v, params: %v, body: %v\n", url, method, params, requestBody) - n, err := ex(result, url, method, params, requestBody) - t.Logf("result %v", result) - return n, err - } -}) -str := "" -n, err := c.Get(&str, "https://${ADDRESS}", nil) +使用filter.Filter进行行为控制和扩展功能,如增加client的输入输出日志: +``` +client := restclient.New(restclient.AddIFilter(filter.NewLog(xlog.GetLogger(), ""))) +resp := &Response{} +err := client.Exchange("http://localhost:8080/test", + request.WithResult(&ret), + request.WithResponse(resp, false)) ``` +可以自行实现IFilter接口,并注册到restclient扩展其功能 ## 认证 ### Basic Auth -```cassandraql +``` o := restclient.New(restclient.SetTimeout(time.Second)) -auth := restclient.NewBasicAuth("user", "password") -c := restclient.NewBasicAuthClient(o, auth) -str := "" -_, err := c.Get(&str, "https://${ADDRESS}", nil) +auth := filter.NewBasicAuth("user", "password") +client := restclient.New(restclient.AddIFilter(auth)) +resp := &Response{} +err := client.Exchange("http://localhost:8080/test", + request.WithResult(&ret), + request.WithResponse(resp, false)) //change username and password auth.ResetCredentials(username, password) @@ -98,12 +118,13 @@ auth.ResetCredentials(username, password) ### Digest Auth -```cassandraql -o := restclient.New(restclient.SetTimeout(time.Second)) -auth := restclient.NewDigestAuth("user", "password") -c := restclient.NewDigestAuthClient(o, auth) -str := "" -_, err := c.Get(&str, "https://${ADDRESS}", nil) +``` +auth := filter.NewDigestAuth("user", "password") +client := restclient.New(restclient.AddIFilter(auth)) +resp := &Response{} +err := client.Exchange("http://localhost:8080/test", + request.WithResult(&ret), + request.WithResponse(resp, false)) //change username and password auth.ResetCredentials(username, password) @@ -111,20 +132,43 @@ auth.ResetCredentials(username, password) ### Token Auth -```cassandraql -o := New(SetTimeout(time.Second)) -auth := NewAccessTokenAuth("mytoken") -c := NewAccessTokenAuthClient(o, auth) -str := "" -_, err := c.Get(&str, "http://localhost:8080/test", nil) +``` +auth := filter.NewAccessTokenAuth("{TOKEN}") +client := restclient.New(restclient.AddIFilter(auth)) +resp := &Response{} +err := client.Exchange("http://localhost:8080/test", + request.WithResult(&ret), + request.WithResponse(resp, false)) -//change token -auth.ResetCredentials(newToken) +//change username and password +auth.ResetCredentials("{TOKEN}") ``` ### 带日志client -```$xslt -c := restclient.NewLogClient(restclient.New(), restclient.NewLog(t.Logf, "test")) -str := "" -_, err := c.Get(&str, "http://${ADDRESS}", nil) ``` +client := restclient.New(restclient.AddIFilter(filter.NewLog(xlog.GetLogger(), ""))) +resp := &Response{} +err := client.Exchange("http://localhost:8080/test", + request.WithResult(&ret), + request.WithResponse(resp, false)) +``` + +### 捕捉panic +``` +client := restclient.New(restclient.AddIFilter(filter.NewRecovery(xlog.GetLogger()))) +resp := &Response{} +err := client.Exchange("http://localhost:8080/test", + request.WithResult(&ret), + request.WithResponse(resp, false)) +``` + +## UrlBuilder +可以使用restclient.NewUrlBuilder为url添加参数,快速构建请求路径 +``` +builder := restclient.NewUrlBuilder("x/:a/tt/:b?") +builder.PathVariable("a", "1") +builder.PathVariable("b", 2) +builder.QueryVariable("c", 100) +builder.QueryVariable("d", 1.1) +url := builder.Build() +``` \ No newline at end of file diff --git a/cookie/cookie_test.go b/cookie/cookie_test.go index 330cb52..e5fe1ce 100644 --- a/cookie/cookie_test.go +++ b/cookie/cookie_test.go @@ -19,6 +19,7 @@ package cookie import ( "context" "fmt" + "github.com/xfali/restclient/v2" "github.com/xfali/restclient/v2/request" "github.com/xfali/restclient/v2/restutil" "net/http" diff --git a/default_restclient.go b/default_restclient.go index 0520ef9..c21ebc4 100644 --- a/default_restclient.go +++ b/default_restclient.go @@ -71,6 +71,7 @@ type defaultRestClient struct { pool buffer.Pool cliCreator HttpClientCreator + jar http.CookieJar acceptFlag AcceptFlag respFlag ResponseBodyFlag transport http.RoundTripper @@ -96,6 +97,7 @@ func New(opts ...Opt) *defaultRestClient { ret.cliCreator = ret.newClient } ret.client = ret.cliCreator() + ret.client.Jar = ret.jar return ret } diff --git a/init_opts.go b/init_opts.go index 1f4ee2f..8bdfc65 100644 --- a/init_opts.go +++ b/init_opts.go @@ -23,70 +23,77 @@ import ( "time" ) -// 设置读写超时 +// SetTimeout 设置读写超时 func SetTimeout(timeout time.Duration) func(client *defaultRestClient) { return func(client *defaultRestClient) { client.timeout = timeout } } -// 配置初始转换器列表 +// SetConverters 配置初始转换器列表 func SetConverters(convs []Converter) func(client *defaultRestClient) { return func(client *defaultRestClient) { client.converters = convs } } -// 添加初始转换器列表 +// AddConverters 添加初始转换器列表 func AddConverters(convs ...Converter) func(client *defaultRestClient) { return func(client *defaultRestClient) { client.converters = append(client.converters, convs...) } } -// 配置连接池 +// SetRoundTripper 配置连接池 func SetRoundTripper(tripper http.RoundTripper) func(client *defaultRestClient) { return func(client *defaultRestClient) { client.transport = tripper } } -// 配置http客户端创建器 +// SetClientCreator 配置http客户端创建器 func SetClientCreator(cliCreator HttpClientCreator) func(client *defaultRestClient) { return func(client *defaultRestClient) { client.cliCreator = cliCreator } } -// 配置是否自动添加accept +// CookieJar 配置http.Client的CookieJar +func CookieJar(jar http.CookieJar) func(client *defaultRestClient) { + return func(client *defaultRestClient) { + client.jar = jar + } +} + +// SetAutoAccept 配置是否自动添加accept func SetAutoAccept(v AcceptFlag) func(client *defaultRestClient) { return func(client *defaultRestClient) { client.acceptFlag = v } } -// 配置是否自动添加accept +// SetResponseBodyFlag 配置是否自动添加accept func SetResponseBodyFlag(v ResponseBodyFlag) func(client *defaultRestClient) { return func(client *defaultRestClient) { client.respFlag = v } } -// 配置内存池 +// SetBufferPool 配置内存池 func SetBufferPool(pool buffer.Pool) func(client *defaultRestClient) { return func(client *defaultRestClient) { client.pool = pool } } -// 增加处理filter +// AddFilter 增加处理filter func AddFilter(filters ...filter.Filter) func(client *defaultRestClient) { return func(client *defaultRestClient) { client.filterManager.Add(filters...) } } -// 增加处理filter +// AddIFilter 增加处理filter func AddIFilter(filters ...filter.IFilter) func(client *defaultRestClient) { return func(client *defaultRestClient) { for _, v := range filters { diff --git a/restutil/urlutil.go b/restutil/urlutil.go index 23c71e5..8a75d0d 100644 --- a/restutil/urlutil.go +++ b/restutil/urlutil.go @@ -118,6 +118,7 @@ type UrlBuilder struct { query map[string]interface{} } +// NewUrlBuilder URL构造器 func NewUrlBuilder(url string) *UrlBuilder { return &UrlBuilder{ url: url, @@ -125,12 +126,14 @@ func NewUrlBuilder(url string) *UrlBuilder { } } -func (b *UrlBuilder) WithDelim(leftDelim, rightDelim string) *UrlBuilder { +// Delims delimiters设置占位符,用于替换url的path参数 +func (b *UrlBuilder) Delims(leftDelim, rightDelim string) *UrlBuilder { b.leftDelim = leftDelim b.rightDelim = rightDelim return b } +// PathVariable 增加path变量参数 func (b *UrlBuilder) PathVariable(key string, value interface{}) *UrlBuilder { if b.path == nil { b.path = map[string]interface{}{} @@ -139,6 +142,7 @@ func (b *UrlBuilder) PathVariable(key string, value interface{}) *UrlBuilder { return b } +// QueryVariable 增加query参数 func (b *UrlBuilder) QueryVariable(key string, value interface{}) *UrlBuilder { if b.query == nil { b.query = map[string]interface{}{} @@ -147,6 +151,7 @@ func (b *UrlBuilder) QueryVariable(key string, value interface{}) *UrlBuilder { return b } +// Build 创建url func (b *UrlBuilder) Build() string { buf := strings.Builder{} if len(b.path) > 0 { diff --git a/test/restclient_test.go b/test/restclient_test.go index 3f1954a..92ebdfe 100644 --- a/test/restclient_test.go +++ b/test/restclient_test.go @@ -456,16 +456,19 @@ func TestErrorStruct(t *testing.T) { }) t.Run("Post", func(t *testing.T) { - ret := testStruct{ + req := testStruct{ Id: 2, Name: "test2", Value: 1.0, CreateTime: time.Now(), } + resp := testStruct{} err := client.Exchange("http://localhost:8080/error", - request.MethodPost(), - request.WithResult(&ret), - request.WithRequestBody(ret)) + restclient.NewRequest(). + MethodPost(). + RequestBody(req). + Result(&resp). + Build()) if err == nil { t.Fatal(err) } else { @@ -476,10 +479,10 @@ func TestErrorStruct(t *testing.T) { } else { t.Log(err.StatusCode()) } - if ret.Id != 2 { - t.Fatal("expect id 2 but get ", ret.Id) + if resp.Id != 2 { + t.Fatal("expect id 2 but get ", resp.Id) } - t.Log(ret) + t.Log(resp) }) }