diff --git a/README.MD b/README.MD index b89197178..7eee0b379 100644 --- a/README.MD +++ b/README.MD @@ -56,17 +56,19 @@ The `Web` component performance of `GoFrame`, please refer to third-party projec # License -`GF` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever. +`GoFrame` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever. # Part Of Users - [Tencent](https://www.tencent.com/) - [ZTE](https://www.zte.com.cn/china/) - [Ant Financial Services](https://www.antfin.com/) -- [MedLinker](https://www.medlinker.com/) +- [VIVO](https://www.vivo.com/) +- [MedLinker](https://www.vivo.com/) - [KuCoin](https://www.kucoin.io/) - [LeYouJia](https://www.leyoujia.com/) - [IGG](https://igg.com) +- [37](https://www.37.com) - [XiMaLaYa](https://www.ximalaya.com) - [ZYBang](https://www.zybang.com/) @@ -80,10 +82,10 @@ This project exists thanks to all the people who contribute. [[Contributors](htt # Donators -If you love `GF`, why not [buy developer a cup of coffee](https://goframe.org/pages/viewpage.action?pageId=1115633)? +If you love `GoFrame`, why not [buy developer a cup of coffee](https://goframe.org/pages/viewpage.action?pageId=1115633)? # Sponsors -We appreciate any kind of sponsorship for `GF` development. If you've got some interesting, please contact WeChat `389961817` / Email `john@goframe.org`. +We appreciate any kind of sponsorship for `GoFrame` development. If you've got some interesting, please contact WeChat `389961817` / Email `john@goframe.org`. diff --git a/README_ZH.MD b/README_ZH.MD index 61404dfbc..9af41ed76 100644 --- a/README_ZH.MD +++ b/README_ZH.MD @@ -72,17 +72,19 @@ golang版本 >= 1.14 # 协议 -`GF` 使用非常友好的 [MIT](LICENSE) 开源协议进行发布,永久`100%`开源免费。 +`GoFrame` 使用非常友好的 [MIT](LICENSE) 开源协议进行发布,永久`100%`开源免费。 # 用户 - [腾讯科技](https://www.tencent.com/) - [中兴通讯](https://www.zte.com.cn/china/) - [蚂蚁金服](https://www.antfin.com/) +- [VIVO](https://www.vivo.com/) - [医联科技](https://www.medlinker.com/) - [库币科技](https://www.kucoin.io/) - [乐有家](https://www.leyoujia.com/) - [IGG](https://igg.com) +- [三七互娱](https://www.37.com) - [喜马拉雅](https://www.ximalaya.com) - [作业帮](https://www.zybang.com/) @@ -96,12 +98,12 @@ golang版本 >= 1.14 # 捐赠 -如果您喜欢`GF`,要不给开发者 [来杯咖啡](https://goframe.org/pages/viewpage.action?pageId=1115633) 吧! +如果您喜欢`GoFrame`,要不给开发者 [来杯咖啡](https://goframe.org/pages/viewpage.action?pageId=1115633) 吧! 请在捐赠时备注您的`github`/`gitee`账号名称。 # 赞助 -赞助支持`GF`框架的快速研发,如果您感兴趣,请联系 微信 `389961817` / 邮件 `john@goframe.org`。 +赞助支持`GoFrame`框架的快速研发,如果您感兴趣,请联系 微信 `389961817` / 邮件 `john@goframe.org`。 # 感谢 JetBrains diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index 7e679c86e..9763f1426 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -250,6 +250,7 @@ type ( const ( defaultModelSafe = false + defaultCharset = `utf8` queryTypeNormal = 0 queryTypeCount = 1 unionTypeNormal = 0 @@ -260,8 +261,8 @@ const ( insertOptionIgnore = 3 defaultBatchNumber = 10 // Per count for batch insert/replace/save. defaultMaxIdleConnCount = 10 // Max idle connection count in pool. - defaultMaxOpenConnCount = 100 // Max open connection count in pool. - defaultMaxConnLifeTime = 30 * time.Second // Max life time for per connection in pool in seconds. + defaultMaxOpenConnCount = 0 // Max open connection count in pool. Default is no limit. + defaultMaxConnLifeTime = 30 * time.Second // Max lifetime for per connection in pool in seconds. ctxTimeoutTypeExec = iota ctxTimeoutTypeQuery ctxTimeoutTypePrepare @@ -409,7 +410,10 @@ func getConfigNodeByGroup(group string, master bool) (*ConfigNode, error) { } } if len(masterList) < 1 { - return nil, gerror.NewCode(gcode.CodeInvalidConfiguration, "at least one master node configuration's need to make sense") + return nil, gerror.NewCode( + gcode.CodeInvalidConfiguration, + "at least one master node configuration's need to make sense", + ) } if len(slaveList) < 1 { slaveList = masterList @@ -420,7 +424,11 @@ func getConfigNodeByGroup(group string, master bool) (*ConfigNode, error) { return getConfigNodeByWeight(slaveList), nil } } else { - return nil, gerror.NewCodef(gcode.CodeInvalidConfiguration, "empty database configuration for item name '%s'", group) + return nil, gerror.NewCodef( + gcode.CodeInvalidConfiguration, + "empty database configuration for item name '%s'", + group, + ) } } @@ -473,7 +481,7 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error } // Default value checks. if node.Charset == "" { - node.Charset = "utf8" + node.Charset = defaultCharset } // Changes the schema. nodeSchema := c.schema.Val() @@ -521,13 +529,7 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error sqlDb.SetMaxOpenConns(defaultMaxOpenConnCount) } if c.config.MaxConnLifeTime > 0 { - // Automatically checks whether MaxConnLifetime is configured using string like: "30s", "60s", etc. - // Or else it is configured just using number, which means value in seconds. - if c.config.MaxConnLifeTime > time.Second { - sqlDb.SetConnMaxLifetime(c.config.MaxConnLifeTime) - } else { - sqlDb.SetConnMaxLifetime(c.config.MaxConnLifeTime * time.Second) - } + sqlDb.SetConnMaxLifetime(c.config.MaxConnLifeTime) } else { sqlDb.SetConnMaxLifetime(defaultMaxConnLifeTime) } diff --git a/database/gdb/gdb_core_tracing.go b/database/gdb/gdb_core_tracing.go index 74f818161..7139d3c64 100644 --- a/database/gdb/gdb_core_tracing.go +++ b/database/gdb/gdb_core_tracing.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" + semconv "go.opentelemetry.io/otel/semconv/v1.7.0" "go.opentelemetry.io/otel/trace" "github.com/gogf/gf/v2" @@ -54,6 +55,7 @@ func (c *Core) addSqlToTracing(ctx context.Context, sql *Sql) { labels = append(labels, gtrace.CommonLabels()...) labels = append(labels, attribute.String(tracingAttrDbType, c.db.GetConfig().Type), + attribute.String(string(semconv.DBStatementKey), sql.Format), ) if c.db.GetConfig().Host != "" { labels = append(labels, attribute.String(tracingAttrDbHost, c.db.GetConfig().Host)) diff --git a/frame/g/g_object.go b/frame/g/g_object.go index 99ae4019d..86fd97004 100644 --- a/frame/g/g_object.go +++ b/frame/g/g_object.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/v2/database/gredis" "github.com/gogf/gf/v2/frame/gins" "github.com/gogf/gf/v2/i18n/gi18n" + "github.com/gogf/gf/v2/net/gclient" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/gtcp" "github.com/gogf/gf/v2/net/gudp" @@ -22,8 +23,8 @@ import ( ) // Client is a convenience function, which creates and returns a new HTTP client. -func Client() *ghttp.Client { - return ghttp.NewClient() +func Client() *gclient.Client { + return gclient.New() } // Server returns an instance of http server with specified name. diff --git a/frame/gins/gins_httpclient.go b/frame/gins/gins_httpclient.go index 8bf8f579c..26f784c5b 100644 --- a/frame/gins/gins_httpclient.go +++ b/frame/gins/gins_httpclient.go @@ -9,7 +9,7 @@ package gins import ( "fmt" - "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/net/gclient" ) const ( @@ -17,11 +17,11 @@ const ( ) // HttpClient returns an instance of http client with specified name. -func HttpClient(name ...interface{}) *ghttp.Client { +func HttpClient(name ...interface{}) *gclient.Client { var ( instanceKey = fmt.Sprintf("%s.%v", frameCoreComponentNameHttpClient, name) ) return localInstances.GetOrSetFuncLock(instanceKey, func() interface{} { - return ghttp.NewClient() - }).(*ghttp.Client) + return gclient.New() + }).(*gclient.Client) } diff --git a/net/ghttp/internal/httputil/httputils.go b/internal/httputil/httputils.go similarity index 100% rename from net/ghttp/internal/httputil/httputils.go rename to internal/httputil/httputils.go diff --git a/net/ghttp/internal/client/client.go b/net/gclient/gclient.go similarity index 97% rename from net/ghttp/internal/client/client.go rename to net/gclient/gclient.go index 4802c6946..49a623253 100644 --- a/net/ghttp/internal/client/client.go +++ b/net/gclient/gclient.go @@ -4,7 +4,8 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +// Package gclient provides convenient http client functionalities. +package gclient import ( "context" @@ -31,7 +32,6 @@ import ( // Client is the HTTP client for HTTP request management. type Client struct { http.Client // Underlying HTTP Client. - dump bool // Mark this request will be dumped. header map[string]string // Custom header map. cookies map[string]string // Custom cookie map. prefix string // Prefix for request. @@ -134,12 +134,6 @@ func (c *Client) SetCookie(key, value string) *Client { return c } -// SetDump enables/disables dump feature for this request. -func (c *Client) SetDump(dump bool) *Client { - c.dump = dump - return c -} - // SetCookieMap sets cookie items with map. func (c *Client) SetCookieMap(m map[string]string) *Client { for k, v := range m { diff --git a/net/ghttp/internal/client/client_bytes.go b/net/gclient/gclient_bytes.go similarity index 99% rename from net/ghttp/internal/client/client_bytes.go rename to net/gclient/gclient_bytes.go index 5cfb5bd17..aa3f1fee6 100644 --- a/net/ghttp/internal/client/client_bytes.go +++ b/net/gclient/gclient_bytes.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +package gclient import ( "context" diff --git a/net/ghttp/internal/client/client_chain.go b/net/gclient/gclient_chain.go similarity index 92% rename from net/ghttp/internal/client/client_chain.go rename to net/gclient/gclient_chain.go index 898360987..12cd40dee 100644 --- a/net/ghttp/internal/client/client_chain.go +++ b/net/gclient/gclient_chain.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +package gclient import ( "time" @@ -94,18 +94,6 @@ func (c *Client) Retry(retryCount int, retryInterval time.Duration) *Client { return newClient } -// Dump is a chaining function, -// which enables/disables dump feature for this request. -func (c *Client) Dump(dump ...bool) *Client { - newClient := c.Clone() - if len(dump) > 0 { - newClient.SetDump(dump[0]) - } else { - newClient.SetDump(true) - } - return newClient -} - // Proxy is a chaining function, // which sets proxy for next request. // Make sure you pass the correct `proxyURL`. diff --git a/net/ghttp/internal/client/client_content.go b/net/gclient/gclient_content.go similarity index 99% rename from net/ghttp/internal/client/client_content.go rename to net/gclient/gclient_content.go index 65d1f7120..ab7951bce 100644 --- a/net/ghttp/internal/client/client_content.go +++ b/net/gclient/gclient_content.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +package gclient import "context" diff --git a/net/ghttp/internal/client/client_dump.go b/net/gclient/gclient_dump.go similarity index 99% rename from net/ghttp/internal/client/client_dump.go rename to net/gclient/gclient_dump.go index 110f3db1d..3c63e9aa7 100644 --- a/net/ghttp/internal/client/client_dump.go +++ b/net/gclient/gclient_dump.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +package gclient import ( "fmt" diff --git a/net/ghttp/internal/client/client_middleware.go b/net/gclient/gclient_middleware.go similarity index 98% rename from net/ghttp/internal/client/client_middleware.go rename to net/gclient/gclient_middleware.go index cfbf8964e..95cdebfba 100644 --- a/net/ghttp/internal/client/client_middleware.go +++ b/net/gclient/gclient_middleware.go @@ -1,4 +1,4 @@ -package client +package gclient import ( "net/http" diff --git a/net/ghttp/internal/client/client_request.go b/net/gclient/gclient_request.go similarity index 97% rename from net/ghttp/internal/client/client_request.go rename to net/gclient/gclient_request.go index c3486ba84..0c3701c29 100644 --- a/net/ghttp/internal/client/client_request.go +++ b/net/gclient/gclient_request.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +package gclient import ( "bytes" @@ -20,10 +20,10 @@ import ( "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/internal/httputil" "github.com/gogf/gf/v2/internal/intlog" "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/utils" - "github.com/gogf/gf/v2/net/ghttp/internal/httputil" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" @@ -292,11 +292,9 @@ func (c *Client) callRequest(req *http.Request) (resp *Response, err error) { // Dump feature. // The request body can be reused for dumping // raw HTTP request-response procedure. - if c.dump { - reqBodyContent, _ := ioutil.ReadAll(req.Body) - resp.requestBody = reqBodyContent - req.Body = utils.NewReadCloser(reqBodyContent, false) - } + reqBodyContent, _ := ioutil.ReadAll(req.Body) + resp.requestBody = reqBodyContent + req.Body = utils.NewReadCloser(reqBodyContent, false) for { if resp.Response, err = c.Do(req); err != nil { // The response might not be nil when err != nil. diff --git a/net/ghttp/internal/client/client_response.go b/net/gclient/gclient_response.go similarity index 99% rename from net/ghttp/internal/client/client_response.go rename to net/gclient/gclient_response.go index 3acc7c795..6f3226889 100644 --- a/net/ghttp/internal/client/client_response.go +++ b/net/gclient/gclient_response.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +package gclient import ( "io/ioutil" diff --git a/net/ghttp/internal/client/client_tracing.go b/net/gclient/gclient_tracing.go similarity index 94% rename from net/ghttp/internal/client/client_tracing.go rename to net/gclient/gclient_tracing.go index 078ad4cb1..8dc3e4256 100644 --- a/net/ghttp/internal/client/client_tracing.go +++ b/net/gclient/gclient_tracing.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +package gclient import ( "fmt" @@ -19,15 +19,15 @@ import ( "go.opentelemetry.io/otel/trace" "github.com/gogf/gf/v2" + "github.com/gogf/gf/v2/internal/httputil" "github.com/gogf/gf/v2/internal/utils" - "github.com/gogf/gf/v2/net/ghttp/internal/httputil" "github.com/gogf/gf/v2/net/gtrace" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" ) const ( - tracingInstrumentName = "github.com/gogf/gf/v2/net/ghttp.Client" + tracingInstrumentName = "github.com/gogf/gf/v2/net/gclient.Client" tracingAttrHttpAddressRemote = "http.address.remote" tracingAttrHttpAddressLocal = "http.address.local" tracingAttrHttpDnsStart = "http.dns.start" diff --git a/net/ghttp/internal/client/client_tracing_tracer.go b/net/gclient/gclient_tracing_tracer.go similarity index 99% rename from net/ghttp/internal/client/client_tracing_tracer.go rename to net/gclient/gclient_tracing_tracer.go index 784597c34..9044d18fe 100644 --- a/net/ghttp/internal/client/client_tracing_tracer.go +++ b/net/gclient/gclient_tracing_tracer.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +package gclient import ( "context" diff --git a/net/ghttp/internal/client/client_var.go b/net/gclient/gclient_var.go similarity index 99% rename from net/ghttp/internal/client/client_var.go rename to net/gclient/gclient_var.go index 2a9a1cac2..938de94d8 100644 --- a/net/ghttp/internal/client/client_var.go +++ b/net/gclient/gclient_var.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package client +package gclient import ( "context" diff --git a/net/ghttp/ghttp_client_websocket.go b/net/gclient/gclient_websocket.go similarity index 82% rename from net/ghttp/ghttp_client_websocket.go rename to net/gclient/gclient_websocket.go index cf99c29e1..3bdb38f02 100644 --- a/net/ghttp/ghttp_client_websocket.go +++ b/net/gclient/gclient_websocket.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package ghttp +package gclient import ( "net/http" @@ -19,8 +19,8 @@ type WebSocketClient struct { *websocket.Dialer } -// NewWebSocketClient New creates and returns a new WebSocketClient object. -func NewWebSocketClient() *WebSocketClient { +// NewWebSocket creates and returns a new WebSocketClient object. +func NewWebSocket() *WebSocketClient { return &WebSocketClient{ &websocket.Dialer{ Proxy: http.ProxyFromEnvironment, diff --git a/net/gclient/gclient_z_example_test.go b/net/gclient/gclient_z_example_test.go new file mode 100644 index 000000000..70e7c46f5 --- /dev/null +++ b/net/gclient/gclient_z_example_test.go @@ -0,0 +1,401 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gclient_test + +import ( + "context" + "fmt" + "time" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" +) + +func init() { + // Default server for client. + p := 8999 + s := g.Server(p) + // HTTP method handlers. + s.Group("/", func(group *ghttp.RouterGroup) { + group.GET("/", func(r *ghttp.Request) { + r.Response.Writef( + "GET: query: %d, %s", + r.GetQuery("id").Int(), + r.GetQuery("name").String(), + ) + }) + group.PUT("/", func(r *ghttp.Request) { + r.Response.Writef( + "PUT: form: %d, %s", + r.GetForm("id").Int(), + r.GetForm("name").String(), + ) + }) + group.POST("/", func(r *ghttp.Request) { + r.Response.Writef( + "POST: form: %d, %s", + r.GetForm("id").Int(), + r.GetForm("name").String(), + ) + }) + group.DELETE("/", func(r *ghttp.Request) { + r.Response.Writef( + "DELETE: form: %d, %s", + r.GetForm("id").Int(), + r.GetForm("name").String(), + ) + }) + group.HEAD("/", func(r *ghttp.Request) { + r.Response.Write("head") + }) + group.OPTIONS("/", func(r *ghttp.Request) { + r.Response.Write("options") + }) + }) + // Client chaining operations handlers. + s.Group("/", func(group *ghttp.RouterGroup) { + group.ALL("/header", func(r *ghttp.Request) { + r.Response.Writef( + "Span-Id: %s, Trace-Id: %s", + r.Header.Get("Span-Id"), + r.Header.Get("Trace-Id"), + ) + }) + group.ALL("/cookie", func(r *ghttp.Request) { + r.Response.Writef( + "SessionId: %s", + r.Cookie.Get("SessionId"), + ) + }) + group.ALL("/json", func(r *ghttp.Request) { + r.Response.Writef( + "Content-Type: %s, id: %d", + r.Header.Get("Content-Type"), + r.Get("id").Int(), + ) + }) + }) + // Other testing handlers. + s.Group("/var", func(group *ghttp.RouterGroup) { + group.ALL("/json", func(r *ghttp.Request) { + r.Response.Write(`{"id":1,"name":"john"}`) + }) + group.ALL("/jsons", func(r *ghttp.Request) { + r.Response.Write(`[{"id":1,"name":"john"}, {"id":2,"name":"smith"}]`) + }) + }) + s.SetAccessLogEnabled(false) + s.SetDumpRouterMap(false) + s.SetPort(p) + err := s.Start() + if err != nil { + panic(err) + } + time.Sleep(time.Millisecond * 500) +} + +func ExampleClient_Header() { + var ( + url = "http://127.0.0.1:8999/header" + header = g.MapStrStr{ + "Span-Id": "0.1", + "Trace-Id": "123456789", + } + ) + content := g.Client().Header(header).PostContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + fmt.Println(content) + + // Output: + // Span-Id: 0.1, Trace-Id: 123456789 +} + +func ExampleClient_HeaderRaw() { + var ( + url = "http://127.0.0.1:8999/header" + headerRaw = ` +User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3950.0 Safari/537.36 +Span-Id: 0.1 +Trace-Id: 123456789 +` + ) + content := g.Client().HeaderRaw(headerRaw).PostContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + fmt.Println(content) + + // Output: + // Span-Id: 0.1, Trace-Id: 123456789 +} + +func ExampleClient_Cookie() { + var ( + url = "http://127.0.0.1:8999/cookie" + cookie = g.MapStrStr{ + "SessionId": "123", + } + ) + content := g.Client().Cookie(cookie).PostContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + fmt.Println(content) + + // Output: + // SessionId: 123 +} + +func ExampleClient_ContentJson() { + var ( + url = "http://127.0.0.1:8999/json" + jsonStr = `{"id":10000,"name":"john"}` + jsonMap = g.Map{ + "id": 10000, + "name": "john", + } + ) + // Post using JSON string. + fmt.Println(g.Client().ContentJson().PostContent(ctx, url, jsonStr)) + // Post using JSON map. + fmt.Println(g.Client().ContentJson().PostContent(ctx, url, jsonMap)) + + // Output: + // Content-Type: application/json, id: 10000 + // Content-Type: application/json, id: 10000 +} + +func ExampleClient_Post() { + url := "http://127.0.0.1:8999" + // Send with string parameter in request body. + r1, err := g.Client().Post(ctx, url, "id=10000&name=john") + if err != nil { + panic(err) + } + defer r1.Close() + fmt.Println(r1.ReadAllString()) + + // Send with map parameter. + r2, err := g.Client().Post(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + if err != nil { + panic(err) + } + defer r2.Close() + fmt.Println(r2.ReadAllString()) + + // Output: + // POST: form: 10000, john + // POST: form: 10000, john +} + +func ExampleClient_PostBytes() { + url := "http://127.0.0.1:8999" + fmt.Println(string(g.Client().PostBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // POST: form: 10000, john +} + +func ExampleClient_PostContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().PostContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: + // POST: form: 10000, john +} + +func ExampleClient_PostVar() { + type User struct { + Id int + Name string + } + var ( + users []User + url = "http://127.0.0.1:8999/var/jsons" + ) + err := g.Client().PostVar(ctx, url).Scan(&users) + if err != nil { + panic(err) + } + fmt.Println(users) + + // Output: + // [{1 john} {2 smith}] +} + +func ExampleClient_Get() { + var ( + ctx = context.Background() + url = "http://127.0.0.1:8999" + ) + + // Send with string parameter along with URL. + r1, err := g.Client().Get(ctx, url+"?id=10000&name=john") + if err != nil { + panic(err) + } + defer r1.Close() + fmt.Println(r1.ReadAllString()) + + // Send with string parameter in request body. + r2, err := g.Client().Get(ctx, url, "id=10000&name=john") + if err != nil { + panic(err) + } + defer r2.Close() + fmt.Println(r2.ReadAllString()) + + // Send with map parameter. + r3, err := g.Client().Get(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + if err != nil { + panic(err) + } + defer r3.Close() + fmt.Println(r3.ReadAllString()) + + // Output: + // GET: query: 10000, john + // GET: query: 10000, john + // GET: query: 10000, john +} + +func ExampleClient_GetBytes() { + var ( + ctx = context.Background() + url = "http://127.0.0.1:8999" + ) + fmt.Println(string(g.Client().GetBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // GET: query: 10000, john +} + +func ExampleClient_GetContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().GetContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: + // GET: query: 10000, john +} + +func ExampleClient_GetVar() { + type User struct { + Id int + Name string + } + var ( + user *User + ctx = context.Background() + url = "http://127.0.0.1:8999/var/json" + ) + err := g.Client().GetVar(ctx, url).Scan(&user) + if err != nil { + panic(err) + } + fmt.Println(user) + + // Output: + // &{1 john} +} + +// ExampleClient_SetProxy a example for `gclient.Client.SetProxy` method. +// please prepare two proxy server before running this example. +// http proxy server listening on `127.0.0.1:1081` +// socks5 proxy server listening on `127.0.0.1:1080` +func ExampleClient_SetProxy() { + // connect to a http proxy server + client := g.Client() + client.SetProxy("http://127.0.0.1:1081") + client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout + response, err := client.Get(ctx, "https://api.ip.sb/ip") + if err != nil { + // err is not nil when your proxy server is down. + // eg. Get "https://api.ip.sb/ip": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused + fmt.Println(err) + } + response.RawDump() + // connect to a http proxy server which needs auth + client.SetProxy("http://user:password:127.0.0.1:1081") + client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout + response, err = client.Get(ctx, "https://api.ip.sb/ip") + if err != nil { + // err is not nil when your proxy server is down. + // eg. Get "https://api.ip.sb/ip": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused + fmt.Println(err) + } + response.RawDump() + + // connect to a socks5 proxy server + client.SetProxy("socks5://127.0.0.1:1080") + client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout + response, err = client.Get(ctx, "https://api.ip.sb/ip") + if err != nil { + // err is not nil when your proxy server is down. + // eg. Get "https://api.ip.sb/ip": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused + fmt.Println(err) + } + fmt.Println(response.RawResponse()) + + // connect to a socks5 proxy server which needs auth + client.SetProxy("socks5://user:password@127.0.0.1:1080") + client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout + response, err = client.Get(ctx, "https://api.ip.sb/ip") + if err != nil { + // err is not nil when your proxy server is down. + // eg. Get "https://api.ip.sb/ip": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused + fmt.Println(err) + } + fmt.Println(response.RawResponse()) +} + +// ExampleClientChain_Proxy a chain version of example for `gclient.Client.Proxy` method. +// please prepare two proxy server before running this example. +// http proxy server listening on `127.0.0.1:1081` +// socks5 proxy server listening on `127.0.0.1:1080` +// for more details, please refer to ExampleClient_SetProxy +func ExampleClient_Proxy() { + var ( + ctx = context.Background() + ) + client := g.Client() + response, err := client.Proxy("http://127.0.0.1:1081").Get(ctx, "https://api.ip.sb/ip") + if err != nil { + // err is not nil when your proxy server is down. + // eg. Get "https://api.ip.sb/ip": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused + fmt.Println(err) + } + fmt.Println(response.RawResponse()) + + client2 := g.Client() + response, err = client2.Proxy("socks5://127.0.0.1:1080").Get(ctx, "https://api.ip.sb/ip") + if err != nil { + // err is not nil when your proxy server is down. + // eg. Get "https://api.ip.sb/ip": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused + fmt.Println(err) + } + fmt.Println(response.RawResponse()) +} diff --git a/net/ghttp/ghttp_z_unit_feature_client_test.go b/net/gclient/gclient_z_unit_test.go similarity index 77% rename from net/ghttp/ghttp_z_unit_feature_client_test.go rename to net/gclient/gclient_z_unit_test.go index e69b08955..a95847c7b 100644 --- a/net/ghttp/ghttp_z_unit_feature_client_test.go +++ b/net/gclient/gclient_z_unit_test.go @@ -4,7 +4,7 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package ghttp_test +package gclient_test import ( "bytes" @@ -15,15 +15,30 @@ import ( "testing" "time" + "github.com/gogf/gf/v2/container/garray" "github.com/gogf/gf/v2/debug/gdebug" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/gclient" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/guid" + "github.com/gorilla/websocket" ) +var ( + ctx = context.TODO() + ports = garray.NewIntArray(true) +) + +func init() { + for i := 7000; i <= 8000; i++ { + ports.Append(i) + } +} + func Test_Client_Basic(t *testing.T) { p, _ := ports.PopRand() s := g.Server(p) @@ -357,7 +372,7 @@ func Test_Client_Middleware(t *testing.T) { str2 = "resp body" ) c := g.Client().SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p)) - c.Use(func(c *ghttp.Client, r *http.Request) (resp *ghttp.ClientResponse, err error) { + c.Use(func(c *gclient.Client, r *http.Request) (resp *gclient.Response, err error) { str1 += "a" resp, err = c.Next(r) if err != nil { @@ -366,7 +381,7 @@ func Test_Client_Middleware(t *testing.T) { str1 += "b" return }) - c.Use(func(c *ghttp.Client, r *http.Request) (resp *ghttp.ClientResponse, err error) { + c.Use(func(c *gclient.Client, r *http.Request) (resp *gclient.Response, err error) { str1 += "c" resp, err = c.Next(r) if err != nil { @@ -375,7 +390,7 @@ func Test_Client_Middleware(t *testing.T) { str1 += "d" return }) - c.Use(func(c *ghttp.Client, r *http.Request) (resp *ghttp.ClientResponse, err error) { + c.Use(func(c *gclient.Client, r *http.Request) (resp *gclient.Response, err error) { str1 += "e" resp, err = c.Next(r) if err != nil { @@ -398,17 +413,17 @@ func Test_Client_Middleware(t *testing.T) { ) c = g.Client().SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p)) - c.Use(func(c *ghttp.Client, r *http.Request) (resp *ghttp.ClientResponse, err error) { + c.Use(func(c *gclient.Client, r *http.Request) (resp *gclient.Response, err error) { str3 += "a" resp, err = c.Next(r) str3 += "b" return }) - c.Use(func(c *ghttp.Client, r *http.Request) (*ghttp.ClientResponse, error) { + c.Use(func(c *gclient.Client, r *http.Request) (*gclient.Response, error) { str3 += "c" return nil, gerror.New(abortStr) }) - c.Use(func(c *ghttp.Client, r *http.Request) (resp *ghttp.ClientResponse, err error) { + c.Use(func(c *gclient.Client, r *http.Request) (resp *gclient.Response, err error) { str3 += "f" resp, err = c.Next(r) str3 += "g" @@ -440,3 +455,85 @@ func Test_Client_Agent(t *testing.T) { t.Assert(c.GetContent(ctx, "/"), "test") }) } + +func Test_Client_Request_13_Dump(t *testing.T) { + p, _ := ports.PopRand() + s := g.Server(p) + s.BindHandler("/hello", func(r *ghttp.Request) { + r.Response.WriteHeader(200) + r.Response.WriteJson(g.Map{"field": "test_for_response_body"}) + }) + s.BindHandler("/hello2", func(r *ghttp.Request) { + r.Response.WriteHeader(200) + r.Response.Writeln(g.Map{"field": "test_for_response_body"}) + }) + s.SetPort(p) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + gtest.C(t, func(t *gtest.T) { + url := fmt.Sprintf("http://127.0.0.1:%d", p) + client := g.Client().SetPrefix(url).ContentJson() + r, err := client.Post(ctx, "/hello", g.Map{"field": "test_for_request_body"}) + t.Assert(err, nil) + dumpedText := r.RawRequest() + t.Assert(gstr.Contains(dumpedText, "test_for_request_body"), true) + dumpedText2 := r.RawResponse() + fmt.Println(dumpedText2) + t.Assert(gstr.Contains(dumpedText2, "test_for_response_body"), true) + + client2 := g.Client().SetPrefix(url).ContentType("text/html") + r2, err := client2.Post(ctx, "/hello2", g.Map{"field": "test_for_request_body"}) + t.Assert(err, nil) + dumpedText3 := r2.RawRequest() + t.Assert(gstr.Contains(dumpedText3, "test_for_request_body"), true) + dumpedText4 := r2.RawResponse() + t.Assert(gstr.Contains(dumpedText4, "test_for_request_body"), false) + }) +} + +func Test_WebSocketClient(t *testing.T) { + p, _ := ports.PopRand() + s := g.Server(p) + s.BindHandler("/ws", func(r *ghttp.Request) { + ws, err := r.WebSocket() + if err != nil { + r.Exit() + } + for { + msgType, msg, err := ws.ReadMessage() + if err != nil { + return + } + if err = ws.WriteMessage(msgType, msg); err != nil { + return + } + } + }) + s.SetPort(p) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + gtest.C(t, func(t *gtest.T) { + client := gclient.NewWebSocket() + client.Proxy = http.ProxyFromEnvironment + client.HandshakeTimeout = time.Minute + + conn, _, err := client.Dial(fmt.Sprintf("ws://127.0.0.1:%d/ws", p), nil) + t.Assert(err, nil) + defer conn.Close() + + msg := []byte("hello") + err = conn.WriteMessage(websocket.TextMessage, msg) + t.Assert(err, nil) + + mt, data, err := conn.ReadMessage() + t.Assert(err, nil) + t.Assert(mt, websocket.TextMessage) + t.Assert(data, msg) + }) +} diff --git a/net/gclient/testdata/upload/file1.txt b/net/gclient/testdata/upload/file1.txt new file mode 100644 index 000000000..1885a2771 --- /dev/null +++ b/net/gclient/testdata/upload/file1.txt @@ -0,0 +1 @@ +file1.txt: This file is for uploading unit test case. \ No newline at end of file diff --git a/net/gclient/testdata/upload/file2.txt b/net/gclient/testdata/upload/file2.txt new file mode 100644 index 000000000..e3167d360 --- /dev/null +++ b/net/gclient/testdata/upload/file2.txt @@ -0,0 +1 @@ +file2.txt: This file is for uploading unit test case. \ No newline at end of file diff --git a/net/ghttp/ghttp_client.go b/net/ghttp/ghttp_client.go deleted file mode 100644 index 3c6235675..000000000 --- a/net/ghttp/ghttp_client.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package ghttp - -import ( - "github.com/gogf/gf/v2/net/ghttp/internal/client" -) - -type ( - Client = client.Client - ClientResponse = client.Response - ClientHandlerFunc = client.HandlerFunc -) - -// NewClient creates and returns a new HTTP client object. -func NewClient() *Client { - return client.New() -} diff --git a/net/ghttp/ghttp_func.go b/net/ghttp/ghttp_func.go index e40f9bed5..ed1177df0 100644 --- a/net/ghttp/ghttp_func.go +++ b/net/ghttp/ghttp_func.go @@ -9,7 +9,7 @@ package ghttp import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/net/ghttp/internal/httputil" + "github.com/gogf/gf/v2/internal/httputil" ) // BuildParams builds the request string for the http client. The `params` can be type of: diff --git a/net/ghttp/ghttp_middleware_tracing.go b/net/ghttp/ghttp_middleware_tracing.go index 8f885bf1b..d74aea77a 100644 --- a/net/ghttp/ghttp_middleware_tracing.go +++ b/net/ghttp/ghttp_middleware_tracing.go @@ -18,9 +18,9 @@ import ( "go.opentelemetry.io/otel/trace" "github.com/gogf/gf/v2" + "github.com/gogf/gf/v2/internal/httputil" "github.com/gogf/gf/v2/internal/utils" - "github.com/gogf/gf/v2/net/ghttp/internal/client" - "github.com/gogf/gf/v2/net/ghttp/internal/httputil" + "github.com/gogf/gf/v2/net/gclient" "github.com/gogf/gf/v2/net/gtrace" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" @@ -38,8 +38,8 @@ const ( ) // MiddlewareClientTracing is a client middleware that enables tracing feature using standards of OpenTelemetry. -func MiddlewareClientTracing(c *Client, r *http.Request) (*ClientResponse, error) { - return client.MiddlewareTracing(c, r) +func MiddlewareClientTracing(c *gclient.Client, r *http.Request) (*gclient.Response, error) { + return gclient.MiddlewareTracing(c, r) } // MiddlewareServerTracing is a serer middleware that enables tracing feature using standards of OpenTelemetry. diff --git a/net/ghttp/ghttp_server_log.go b/net/ghttp/ghttp_server_log.go index 80b29cd78..7743f1f23 100644 --- a/net/ghttp/ghttp_server_log.go +++ b/net/ghttp/ghttp_server_log.go @@ -10,6 +10,7 @@ import ( "fmt" "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/text/gstr" ) // handleAccessLog handles the access logging for server. @@ -26,8 +27,7 @@ func (s *Server) handleAccessLog(r *Request) { Printf( r.Context(), `%d "%s %s %s %s %s" %.3f, %s, "%s", "%s"`, - r.Response.Status, - r.Method, scheme, r.Host, r.URL.String(), r.Proto, + r.Response.Status, r.Method, scheme, r.Host, r.URL.String(), r.Proto, float64(r.LeaveTime-r.EnterTime)/1000, r.GetClientIp(), r.Referer(), r.UserAgent(), ) @@ -39,16 +39,24 @@ func (s *Server) handleErrorLog(err error, r *Request) { if !s.IsErrorLogEnabled() { return } - - scheme := "http" + var ( + code = gerror.Code(err) + scheme = "http" + codeDetail = code.Detail() + codeDetailStr string + ) if r.TLS != nil { scheme = "https" } + if codeDetail != nil { + codeDetailStr = gstr.Replace(fmt.Sprintf(`%+v`, codeDetail), "\n", " ") + } content := fmt.Sprintf( - `%d "%s %s %s %s %s" %.3f, %s, "%s", "%s"`, + `%d "%s %s %s %s %s" %.3f, %s, "%s", "%s", %d, "%s", "%+v"`, r.Response.Status, r.Method, scheme, r.Host, r.URL.String(), r.Proto, float64(r.LeaveTime-r.EnterTime)/1000, r.GetClientIp(), r.Referer(), r.UserAgent(), + code.Code(), code.Message(), codeDetailStr, ) if s.config.ErrorStack { if stack := gerror.Stack(err); stack != "" { diff --git a/net/ghttp/ghttp_z_example_client_test.go b/net/ghttp/ghttp_z_example_client_test.go deleted file mode 100644 index 00af6290d..000000000 --- a/net/ghttp/ghttp_z_example_client_test.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package ghttp_test - -import ( - "fmt" - - "github.com/gogf/gf/v2/frame/g" -) - -func ExampleClient_Header() { - var ( - url = "http://127.0.0.1:8999/header" - header = g.MapStrStr{ - "Span-Id": "0.1", - "Trace-Id": "123456789", - } - ) - content := g.Client().Header(header).PostContent(ctx, url, g.Map{ - "id": 10000, - "name": "john", - }) - fmt.Println(content) - - // Output: - // Span-Id: 0.1, Trace-Id: 123456789 -} - -func ExampleClient_HeaderRaw() { - var ( - url = "http://127.0.0.1:8999/header" - headerRaw = ` -User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3950.0 Safari/537.36 -Span-Id: 0.1 -Trace-Id: 123456789 -` - ) - content := g.Client().HeaderRaw(headerRaw).PostContent(ctx, url, g.Map{ - "id": 10000, - "name": "john", - }) - fmt.Println(content) - - // Output: - // Span-Id: 0.1, Trace-Id: 123456789 -} - -func ExampleClient_Cookie() { - var ( - url = "http://127.0.0.1:8999/cookie" - cookie = g.MapStrStr{ - "SessionId": "123", - } - ) - content := g.Client().Cookie(cookie).PostContent(ctx, url, g.Map{ - "id": 10000, - "name": "john", - }) - fmt.Println(content) - - // Output: - // SessionId: 123 -} - -func ExampleClient_ContentJson() { - var ( - url = "http://127.0.0.1:8999/json" - jsonStr = `{"id":10000,"name":"john"}` - jsonMap = g.Map{ - "id": 10000, - "name": "john", - } - ) - // Post using JSON string. - fmt.Println(g.Client().ContentJson().PostContent(ctx, url, jsonStr)) - // Post using JSON map. - fmt.Println(g.Client().ContentJson().PostContent(ctx, url, jsonMap)) - - // Output: - // Content-Type: application/json, id: 10000 - // Content-Type: application/json, id: 10000 -} diff --git a/net/ghttp/ghttp_z_example_get_test.go b/net/ghttp/ghttp_z_example_get_test.go deleted file mode 100644 index b839ae602..000000000 --- a/net/ghttp/ghttp_z_example_get_test.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package ghttp_test - -import ( - "context" - "fmt" - - "github.com/gogf/gf/v2/frame/g" -) - -func ExampleClient_Get() { - var ( - ctx = context.Background() - url = "http://127.0.0.1:8999" - ) - - // Send with string parameter along with URL. - r1, err := g.Client().Get(ctx, url+"?id=10000&name=john") - if err != nil { - panic(err) - } - defer r1.Close() - fmt.Println(r1.ReadAllString()) - - // Send with string parameter in request body. - r2, err := g.Client().Get(ctx, url, "id=10000&name=john") - if err != nil { - panic(err) - } - defer r2.Close() - fmt.Println(r2.ReadAllString()) - - // Send with map parameter. - r3, err := g.Client().Get(ctx, url, g.Map{ - "id": 10000, - "name": "john", - }) - if err != nil { - panic(err) - } - defer r3.Close() - fmt.Println(r3.ReadAllString()) - - // Output: - // GET: query: 10000, john - // GET: query: 10000, john - // GET: query: 10000, john -} - -func ExampleClient_GetBytes() { - var ( - ctx = context.Background() - url = "http://127.0.0.1:8999" - ) - fmt.Println(string(g.Client().GetBytes(ctx, url, g.Map{ - "id": 10000, - "name": "john", - }))) - - // Output: - // GET: query: 10000, john -} - -func ExampleClient_GetContent() { - url := "http://127.0.0.1:8999" - fmt.Println(g.Client().GetContent(ctx, url, g.Map{ - "id": 10000, - "name": "john", - })) - - // Output: - // GET: query: 10000, john -} - -func ExampleClient_GetVar() { - type User struct { - Id int - Name string - } - var ( - user *User - ctx = context.Background() - url = "http://127.0.0.1:8999/var/json" - ) - err := g.Client().GetVar(ctx, url).Scan(&user) - if err != nil { - panic(err) - } - fmt.Println(user) - - // Output: - // &{1 john} -} diff --git a/net/ghttp/ghttp_z_example_init_test.go b/net/ghttp/ghttp_z_example_init_test.go deleted file mode 100644 index 6bc446825..000000000 --- a/net/ghttp/ghttp_z_example_init_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package ghttp_test - -import ( - "time" - - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/net/ghttp" -) - -func init() { - p := 8999 - s := g.Server(p) - // HTTP method handlers. - s.Group("/", func(group *ghttp.RouterGroup) { - group.GET("/", func(r *ghttp.Request) { - r.Response.Writef( - "GET: query: %d, %s", - r.GetQuery("id").Int(), - r.GetQuery("name").String(), - ) - }) - group.PUT("/", func(r *ghttp.Request) { - r.Response.Writef( - "PUT: form: %d, %s", - r.GetForm("id").Int(), - r.GetForm("name").String(), - ) - }) - group.POST("/", func(r *ghttp.Request) { - r.Response.Writef( - "POST: form: %d, %s", - r.GetForm("id").Int(), - r.GetForm("name").String(), - ) - }) - group.DELETE("/", func(r *ghttp.Request) { - r.Response.Writef( - "DELETE: form: %d, %s", - r.GetForm("id").Int(), - r.GetForm("name").String(), - ) - }) - group.HEAD("/", func(r *ghttp.Request) { - r.Response.Write("head") - }) - group.OPTIONS("/", func(r *ghttp.Request) { - r.Response.Write("options") - }) - }) - // Client chaining operations handlers. - s.Group("/", func(group *ghttp.RouterGroup) { - group.ALL("/header", func(r *ghttp.Request) { - r.Response.Writef( - "Span-Id: %s, Trace-Id: %s", - r.Header.Get("Span-Id"), - r.Header.Get("Trace-Id"), - ) - }) - group.ALL("/cookie", func(r *ghttp.Request) { - r.Response.Writef( - "SessionId: %s", - r.Cookie.Get("SessionId"), - ) - }) - group.ALL("/json", func(r *ghttp.Request) { - r.Response.Writef( - "Content-Type: %s, id: %d", - r.Header.Get("Content-Type"), - r.Get("id").Int(), - ) - }) - }) - // Other testing handlers. - s.Group("/var", func(group *ghttp.RouterGroup) { - group.ALL("/json", func(r *ghttp.Request) { - r.Response.Write(`{"id":1,"name":"john"}`) - }) - group.ALL("/jsons", func(r *ghttp.Request) { - r.Response.Write(`[{"id":1,"name":"john"}, {"id":2,"name":"smith"}]`) - }) - }) - s.SetAccessLogEnabled(false) - s.SetDumpRouterMap(false) - s.SetPort(p) - err := s.Start() - if err != nil { - panic(err) - } - time.Sleep(time.Millisecond * 500) -} diff --git a/net/ghttp/ghttp_z_example_post_test.go b/net/ghttp/ghttp_z_example_post_test.go deleted file mode 100644 index 6c573645d..000000000 --- a/net/ghttp/ghttp_z_example_post_test.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package ghttp_test - -import ( - "fmt" - - "github.com/gogf/gf/v2/frame/g" -) - -func ExampleClient_Post() { - url := "http://127.0.0.1:8999" - // Send with string parameter in request body. - r1, err := g.Client().Post(ctx, url, "id=10000&name=john") - if err != nil { - panic(err) - } - defer r1.Close() - fmt.Println(r1.ReadAllString()) - - // Send with map parameter. - r2, err := g.Client().Post(ctx, url, g.Map{ - "id": 10000, - "name": "john", - }) - if err != nil { - panic(err) - } - defer r2.Close() - fmt.Println(r2.ReadAllString()) - - // Output: - // POST: form: 10000, john - // POST: form: 10000, john -} - -func ExampleClient_PostBytes() { - url := "http://127.0.0.1:8999" - fmt.Println(string(g.Client().PostBytes(ctx, url, g.Map{ - "id": 10000, - "name": "john", - }))) - - // Output: - // POST: form: 10000, john -} - -func ExampleClient_PostContent() { - url := "http://127.0.0.1:8999" - fmt.Println(g.Client().PostContent(ctx, url, g.Map{ - "id": 10000, - "name": "john", - })) - - // Output: - // POST: form: 10000, john -} - -func ExampleClient_PostVar() { - type User struct { - Id int - Name string - } - var ( - users []User - url = "http://127.0.0.1:8999/var/jsons" - ) - err := g.Client().PostVar(ctx, url).Scan(&users) - if err != nil { - panic(err) - } - fmt.Println(users) - - // Output: - // [{1 john} {2 smith}] -} diff --git a/net/ghttp/ghttp_z_example_test.go b/net/ghttp/ghttp_z_example_test.go index 61aeba006..ce07cda1f 100644 --- a/net/ghttp/ghttp_z_example_test.go +++ b/net/ghttp/ghttp_z_example_test.go @@ -7,16 +7,12 @@ package ghttp_test import ( - "context" - "fmt" - "time" - "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gfile" ) -func ExampleHelloWorld() { +func ExampleServer_Run() { s := g.Server() s.BindHandler("/", func(r *ghttp.Request) { r.Response.Write("hello world") @@ -45,92 +41,3 @@ func ExampleUploadFile_Save() { s.SetPort(8999) s.Run() } - -func ExampleClientResponse_RawDump() { - var ( - ctx = context.Background() - ) - response, err := g.Client().Get(ctx, "https://goframe.org") - if err != nil { - panic(err) - } - response.RawDump() -} - -// ExampleClient_SetProxy a example for `ghttp.Client.SetProxy` method. -// please prepare two proxy server before running this example. -// http proxy server listening on `127.0.0.1:1081` -// socks5 proxy server listening on `127.0.0.1:1080` -func ExampleClient_SetProxy() { - // connect to a http proxy server - client := g.Client() - client.SetProxy("http://127.0.0.1:1081") - client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout - response, err := client.Get(ctx, "https://api.ip.sb/ip") - if err != nil { - // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) - } - response.RawDump() - // connect to a http proxy server which needs auth - client.SetProxy("http://user:password:127.0.0.1:1081") - client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout - response, err = client.Get(ctx, "https://api.ip.sb/ip") - if err != nil { - // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) - } - response.RawDump() - - // connect to a socks5 proxy server - client.SetProxy("socks5://127.0.0.1:1080") - client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout - response, err = client.Get(ctx, "https://api.ip.sb/ip") - if err != nil { - // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) - } - fmt.Println(response.RawResponse()) - - // connect to a socks5 proxy server which needs auth - client.SetProxy("socks5://user:password@127.0.0.1:1080") - client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout - response, err = client.Get(ctx, "https://api.ip.sb/ip") - if err != nil { - // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) - } - fmt.Println(response.RawResponse()) -} - -// ExampleClientChain_Proxy a chain version of example for `ghttp.Client.Proxy` method. -// please prepare two proxy server before running this example. -// http proxy server listening on `127.0.0.1:1081` -// socks5 proxy server listening on `127.0.0.1:1080` -// for more details, please refer to ExampleClient_SetProxy -func ExampleClientChain_Proxy() { - var ( - ctx = context.Background() - ) - client := g.Client() - response, err := client.Proxy("http://127.0.0.1:1081").Get(ctx, "https://api.ip.sb/ip") - if err != nil { - // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) - } - fmt.Println(response.RawResponse()) - - client2 := g.Client() - response, err = client2.Proxy("socks5://127.0.0.1:1080").Get(ctx, "https://api.ip.sb/ip") - if err != nil { - // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) - } - fmt.Println(response.RawResponse()) -} diff --git a/net/ghttp/ghttp_z_unit_feature_client_dump_test.go b/net/ghttp/ghttp_z_unit_feature_client_dump_test.go deleted file mode 100644 index c1a89a07e..000000000 --- a/net/ghttp/ghttp_z_unit_feature_client_dump_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package ghttp_test - -import ( - "fmt" - "testing" - "time" - - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/net/ghttp" - "github.com/gogf/gf/v2/test/gtest" - "github.com/gogf/gf/v2/text/gstr" -) - -func Test_Client_Request_13_Dump(t *testing.T) { - p, _ := ports.PopRand() - s := g.Server(p) - s.BindHandler("/hello", func(r *ghttp.Request) { - r.Response.WriteHeader(200) - r.Response.WriteJson(g.Map{"field": "test_for_response_body"}) - }) - s.BindHandler("/hello2", func(r *ghttp.Request) { - r.Response.WriteHeader(200) - r.Response.Writeln(g.Map{"field": "test_for_response_body"}) - }) - s.SetPort(p) - s.SetDumpRouterMap(false) - s.Start() - defer s.Shutdown() - - time.Sleep(100 * time.Millisecond) - gtest.C(t, func(t *gtest.T) { - url := fmt.Sprintf("http://127.0.0.1:%d", p) - client := g.Client().SetPrefix(url).ContentJson().SetDump(true) - r, err := client.Post(ctx, "/hello", g.Map{"field": "test_for_request_body"}) - t.Assert(err, nil) - dumpedText := r.RawRequest() - t.Assert(gstr.Contains(dumpedText, "test_for_request_body"), true) - dumpedText2 := r.RawResponse() - fmt.Println(dumpedText2) - t.Assert(gstr.Contains(dumpedText2, "test_for_response_body"), true) - - client2 := g.Client().SetPrefix(url).ContentType("text/html") - r2, err := client2.Dump().Post(ctx, "/hello2", g.Map{"field": "test_for_request_body"}) - t.Assert(err, nil) - dumpedText3 := r2.RawRequest() - t.Assert(gstr.Contains(dumpedText3, "test_for_request_body"), true) - dumpedText4 := r2.RawResponse() - t.Assert(gstr.Contains(dumpedText4, "test_for_request_body"), false) - }) -} diff --git a/net/ghttp/ghttp_z_unit_feature_router_group_rest_test.go b/net/ghttp/ghttp_z_unit_feature_router_group_rest_test.go index 509562fdf..52cc12578 100644 --- a/net/ghttp/ghttp_z_unit_feature_router_group_rest_test.go +++ b/net/ghttp/ghttp_z_unit_feature_router_group_rest_test.go @@ -4,7 +4,6 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// 分组路由测试 package ghttp_test import ( diff --git a/net/ghttp/ghttp_z_unit_feature_websocket_client_test.go b/net/ghttp/ghttp_z_unit_feature_websocket_client_test.go deleted file mode 100644 index 56c2c794d..000000000 --- a/net/ghttp/ghttp_z_unit_feature_websocket_client_test.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package ghttp_test - -import ( - "fmt" - "net/http" - "testing" - "time" - - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/net/ghttp" - "github.com/gogf/gf/v2/test/gtest" - "github.com/gorilla/websocket" -) - -func Test_WebSocketClient(t *testing.T) { - p, _ := ports.PopRand() - s := g.Server(p) - s.BindHandler("/ws", func(r *ghttp.Request) { - ws, err := r.WebSocket() - if err != nil { - r.Exit() - } - for { - msgType, msg, err := ws.ReadMessage() - if err != nil { - return - } - if err = ws.WriteMessage(msgType, msg); err != nil { - return - } - } - }) - s.SetPort(p) - s.SetDumpRouterMap(false) - s.Start() - defer s.Shutdown() - - time.Sleep(100 * time.Millisecond) - gtest.C(t, func(t *gtest.T) { - client := ghttp.NewWebSocketClient() - client.Proxy = http.ProxyFromEnvironment - client.HandshakeTimeout = time.Minute - - conn, _, err := client.Dial(fmt.Sprintf("ws://127.0.0.1:%d/ws", p), nil) - t.Assert(err, nil) - defer conn.Close() - - msg := []byte("hello") - err = conn.WriteMessage(websocket.TextMessage, msg) - t.Assert(err, nil) - - mt, data, err := conn.ReadMessage() - t.Assert(err, nil) - t.Assert(mt, websocket.TextMessage) - t.Assert(data, msg) - }) -} diff --git a/net/gtrace/gtrace.go b/net/gtrace/gtrace.go index 6b14ca8ac..afcc505d3 100644 --- a/net/gtrace/gtrace.go +++ b/net/gtrace/gtrace.go @@ -12,16 +12,17 @@ import ( "os" "strings" - "github.com/gogf/gf/v2/internal/command" - "github.com/gogf/gf/v2/util/gconv" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/propagation" + semconv "go.opentelemetry.io/otel/semconv/v1.7.0" "go.opentelemetry.io/otel/trace" "github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gvar" + "github.com/gogf/gf/v2/internal/command" "github.com/gogf/gf/v2/net/gipv4" + "github.com/gogf/gf/v2/util/gconv" ) const ( @@ -68,6 +69,7 @@ func CommonLabels() []attribute.KeyValue { return []attribute.KeyValue{ attribute.String(tracingCommonKeyIpHostname, hostname), attribute.String(tracingCommonKeyIpIntranet, intranetIpStr), + semconv.HostNameKey.String(hostname), } } diff --git a/os/gcfg/gcfg_adapter_file.go b/os/gcfg/gcfg_adapter_file.go index 2c7dbe50d..fa546cf64 100644 --- a/os/gcfg/gcfg_adapter_file.go +++ b/os/gcfg/gcfg_adapter_file.go @@ -40,11 +40,15 @@ var ( supportedFileTypes = []string{"toml", "yaml", "yml", "json", "ini", "xml"} // All supported file types suffixes. localInstances = gmap.NewStrAnyMap(true) // Instances map containing configuration instances. customConfigContentMap = gmap.NewStrStrMap(true) // Customized configuration content. + // Prefix array for trying searching in resource manager. resourceTryFiles = []string{ "", "/", "config/", "config", "/config", "/config/", "manifest/config/", "manifest/config", "/manifest/config", "/manifest/config/", } + + // Prefix array for trying searching in local system. + localSystemTryFiles = []string{"", "config/", "manifest/config"} ) // NewAdapterFile returns a new configuration management object. diff --git a/os/gcfg/gcfg_adapter_file_path.go b/os/gcfg/gcfg_adapter_file_path.go index c826ed13c..a21f79ced 100644 --- a/os/gcfg/gcfg_adapter_file_path.go +++ b/os/gcfg/gcfg_adapter_file_path.go @@ -168,15 +168,18 @@ func (c *AdapterFile) GetFilePath(fileName ...string) (path string, err error) { }) } c.autoCheckAndAddMainPkgPathToSearchPaths() - // Searching the file system. + // Searching local file system. c.searchPaths.RLockFunc(func(array []string) { for _, prefix := range array { prefix = gstr.TrimRight(prefix, `\/`) - if path, _ = gspath.Search(prefix, usedFileName); path != "" { - return - } - if path, _ = gspath.Search(prefix+gfile.Separator+"config", usedFileName); path != "" { - return + for _, tryFile := range localSystemTryFiles { + relativePath := gstr.TrimRight( + gfile.Join(tryFile, usedFileName), + `\/`, + ) + if path, _ = gspath.Search(prefix, relativePath); path != "" { + return + } } } }) @@ -192,12 +195,13 @@ func (c *AdapterFile) GetFilePath(fileName ...string) (path string, err error) { )) c.searchPaths.RLockFunc(func(array []string) { index := 1 - for _, v := range array { - v = gstr.TrimRight(v, `\/`) - buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v)) - index++ - buffer.WriteString(fmt.Sprintf("\n%d. %s", index, v+gfile.Separator+"config")) - index++ + for _, prefix := range array { + prefix = gstr.TrimRight(prefix, `\/`) + for _, tryFile := range localSystemTryFiles { + prefixPath := gfile.Join(prefix, tryFile) + buffer.WriteString(fmt.Sprintf("\n%d. %s", index, prefixPath)) + index++ + } } }) } else { diff --git a/os/gcmd/gcmd_command.go b/os/gcmd/gcmd_command.go index 998129850..b946f9828 100644 --- a/os/gcmd/gcmd_command.go +++ b/os/gcmd/gcmd_command.go @@ -26,6 +26,7 @@ type Command struct { HelpFunc Function // Custom help function Examples string // Usage examples. Additional string // Additional info about this command, which will be appended to the end of help info. + NeedArgs bool // NeedArgs specifies this command needs arguments. Strict bool // Strict parsing options, which means it returns error if invalid option given. parent *Command // Parent command for internal usage. commands []Command // Sub commands of this command. diff --git a/os/gcmd/gcmd_command_help.go b/os/gcmd/gcmd_command_help.go index 4fd00faff..29c7facf4 100644 --- a/os/gcmd/gcmd_command_help.go +++ b/os/gcmd/gcmd_command_help.go @@ -17,8 +17,16 @@ import ( // Print prints help info to stdout for current command. func (c *Command) Print() { - prefix := gstr.Repeat(" ", 4) - buffer := bytes.NewBuffer(nil) + var ( + prefix = gstr.Repeat(" ", 4) + buffer = bytes.NewBuffer(nil) + options = make([]Option, len(c.Options)) + ) + // Copy options for printing. + copy(options, c.Options) + // Add built-in help option, just for info only. + options = append(options, defaultHelpOption) + // Usage. if c.Usage != "" || c.Name != "" { buffer.WriteString("USAGE\n") @@ -66,13 +74,13 @@ func (c *Command) Print() { } // Option. - if len(c.Options) > 0 { + if len(options) > 0 { buffer.WriteString("OPTION\n") var ( nameStr string maxSpaceLength = 0 ) - for _, option := range c.Options { + for _, option := range options { if option.Short != "" { nameStr = fmt.Sprintf("-%s,\t--%s", option.Short, option.Name) } else { @@ -82,7 +90,7 @@ func (c *Command) Print() { maxSpaceLength = len(nameStr) } } - for _, option := range c.Options { + for _, option := range options { if option.Short != "" { nameStr = fmt.Sprintf("-%s,\t--%s", option.Short, option.Name) } else { @@ -126,8 +134,6 @@ func (c *Command) Print() { } func (c *Command) defaultHelpFunc(ctx context.Context, parser *Parser) error { - // Add built-in help option, just for info only. - c.Options = append(c.Options, defaultHelpOption) // Print command help info to stdout. c.Print() return nil diff --git a/os/gcmd/gcmd_command_object.go b/os/gcmd/gcmd_command_object.go index 2449a73f0..eaadf570b 100644 --- a/os/gcmd/gcmd_command_object.go +++ b/os/gcmd/gcmd_command_object.go @@ -24,8 +24,11 @@ import ( ) const ( - tagNameDc = `dc` - tagNameAd = `ad` + tagNameDc = `dc` + tagNameAd = `ad` + tagNameEg = `eg` + tagNameArgs = `args` + tagNameRoot = `root` ) var ( @@ -50,8 +53,9 @@ func NewFromObject(object interface{}) (rootCmd Command, err error) { } // Sub command creating. var ( - nameSet = gset.NewStrSet() - subCommands []Command + nameSet = gset.NewStrSet() + rootCommandName = gmeta.Get(object, tagNameRoot).String() + subCommands []Command ) for i := 0; i < originValueAndKind.InputValue.NumMethod(); i++ { var ( @@ -69,7 +73,19 @@ func NewFromObject(object interface{}) (rootCmd Command, err error) { ) return } - subCommands = append(subCommands, methodCommand) + if rootCommandName == methodCommand.Name { + if rootCmd.Func == nil { + rootCmd.Func = methodCommand.Func + } + if rootCmd.FuncWithValue == nil { + rootCmd.FuncWithValue = methodCommand.FuncWithValue + } + if len(rootCmd.Options) == 0 { + rootCmd.Options = methodCommand.Options + } + } else { + subCommands = append(subCommands, methodCommand) + } } if len(subCommands) > 0 { err = rootCmd.AddCommand(subCommands...) @@ -99,9 +115,15 @@ func newCommandFromObjectMeta(object interface{}) (command Command, err error) { ) return } + if !command.NeedArgs { + command.NeedArgs = gconv.Bool(metaData[tagNameArgs]) + } if command.Description == "" { command.Description = metaData[tagNameDc] } + if command.Examples == "" { + command.Examples = metaData[tagNameEg] + } if command.Additional == "" { command.Additional = metaData[tagNameAd] } @@ -185,7 +207,7 @@ func newCommandFromMethod(object interface{}, method reflect.Value) (command Com // Create function that has value return. command.FuncWithValue = func(ctx context.Context, parser *Parser) (out interface{}, err error) { - ctx = context.WithValue(ctx, CtxKeyParser, command) + ctx = context.WithValue(ctx, CtxKeyParser, parser) defer func() { if exception := recover(); exception != nil { diff --git a/os/gcmd/gcmd_command_run.go b/os/gcmd/gcmd_command_run.go index 3f96a9fb6..7a700ebe6 100644 --- a/os/gcmd/gcmd_command_run.go +++ b/os/gcmd/gcmd_command_run.go @@ -30,11 +30,7 @@ func (c *Command) RunWithValue(ctx context.Context) (value interface{}, err erro } args := parser.GetArgAll() if len(args) == 1 { - // If no arguments passed but binary name, it then prints help. - if c.HelpFunc != nil { - return nil, c.HelpFunc(ctx, parser) - } - return nil, c.defaultHelpFunc(ctx, parser) + return c.doRun(ctx, parser) } // Exclude the root binary name. @@ -85,6 +81,10 @@ func (c *Command) doRun(ctx context.Context, parser *Parser) (value interface{}, // reParse re-parses the arguments using option configuration of current command. func (c *Command) reParse(ctx context.Context, parser *Parser) (*Parser, error) { + if len(c.Options) == 0 { + return parser, nil + } + var ( optionKey string supportedOptions = make(map[string]bool) @@ -106,6 +106,12 @@ func (c *Command) searchCommand(args []string) *Command { return nil } for _, cmd := range c.commands { + // If this command needs argument, + // it then gives all its left arguments to it. + if cmd.NeedArgs { + return &cmd + } + // Recursively searching the command. if cmd.Name == args[0] { leftArgs := args[1:] if len(leftArgs) == 0 { diff --git a/os/gcmd/gcmd_z_unit_feature_object_test.go b/os/gcmd/gcmd_z_unit_feature_object_test.go index a528b1703..61e41021f 100644 --- a/os/gcmd/gcmd_z_unit_feature_object_test.go +++ b/os/gcmd/gcmd_z_unit_feature_object_test.go @@ -96,3 +96,90 @@ func Test_Command_AddObject(t *testing.T) { t.Assert(value, `{"Content":"john"}`) }) } + +type TestObjectForRootTag struct { + g.Meta `name:"root" root:"root"` +} + +type TestObjectForRootTagEnvInput struct { + g.Meta `name:"env" usage:"root env" brief:"root env command" dc:"root env command description" ad:"root env command ad"` +} +type TestObjectForRootTagEnvOutput struct{} + +type TestObjectForRootTagTestInput struct { + g.Meta `name:"root"` + Name string `v:"required" short:"n" orphan:"false" brief:"name for test command"` +} +type TestObjectForRootTagTestOutput struct { + Content string +} + +func (TestObjectForRootTag) Env(ctx context.Context, in TestObjectForRootTagEnvInput) (out *TestObjectForRootTagEnvOutput, err error) { + return +} + +func (TestObjectForRootTag) Root(ctx context.Context, in TestObjectForRootTagTestInput) (out *TestObjectForRootTagTestOutput, err error) { + out = &TestObjectForRootTagTestOutput{ + Content: in.Name, + } + return +} + +func Test_Command_RootTag(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + ctx = gctx.New() + ) + cmd, err := gcmd.NewFromObject(TestObjectForRootTag{}) + t.AssertNil(err) + + os.Args = []string{"root", "-n=john"} + value, err := cmd.RunWithValue(ctx) + t.AssertNil(err) + t.Assert(value, `{"Content":"john"}`) + }) +} + +type TestObjectForNeedArgs struct { + g.Meta `name:"root" root:"root"` +} + +type TestObjectForNeedArgsEnvInput struct { + g.Meta `name:"env" usage:"root env" brief:"root env command" dc:"root env command description" ad:"root env command ad"` +} +type TestObjectForNeedArgsEnvOutput struct{} + +type TestObjectForNeedArgsTestInput struct { + g.Meta `name:"test" args:"true"` + Name string `v:"required" short:"n" orphan:"false" brief:"name for test command"` +} +type TestObjectForNeedArgsTestOutput struct { + Args []string +} + +func (TestObjectForNeedArgs) Env(ctx context.Context, in TestObjectForNeedArgsEnvInput) (out *TestObjectForNeedArgsEnvOutput, err error) { + return +} + +func (TestObjectForNeedArgs) Test(ctx context.Context, in TestObjectForNeedArgsTestInput) (out *TestObjectForNeedArgsTestOutput, err error) { + parser := gcmd.ParserFromCtx(ctx) + out = &TestObjectForNeedArgsTestOutput{ + Args: parser.GetArgAll(), + } + return +} + +func Test_Command_NeedArgs(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + ctx = gctx.New() + ) + cmd, err := gcmd.NewFromObject(TestObjectForNeedArgs{}) + t.AssertNil(err) + + os.Args = []string{"root", "test", "a", "b", "c", "-n=john"} + value, err := cmd.RunWithValue(ctx) + t.AssertNil(err) + t.Assert(value, `{"Args":["root","test","a","b","c"]}`) + }) +} diff --git a/os/gcron/gcron_schedule.go b/os/gcron/gcron_z_unit_schedule.go similarity index 75% rename from os/gcron/gcron_schedule.go rename to os/gcron/gcron_z_unit_schedule.go index 71da89d95..7aae47b2e 100644 --- a/os/gcron/gcron_schedule.go +++ b/os/gcron/gcron_z_unit_schedule.go @@ -189,7 +189,9 @@ func parsePatternItem(item string, min int, max int, allowQuestionMark bool) (ma return nil, gerror.NewCodef(gcode.CodeInvalidParameter, `invalid pattern item: "%s"`, item) } else { rangeMin = number - rangeMax = number + if len(intervalArray) == 1 { + rangeMax = number + } } } if len(rangeArray) == 2 { @@ -263,3 +265,105 @@ func (s *cronSchedule) meet(t time.Time) bool { return true } } + +// Next returns the next time this schedule is activated, greater than the given +// time. If no time can be found to satisfy the schedule, return the zero time. +func (s *cronSchedule) Next(t time.Time) time.Time { + if s.every != 0 { + diff := t.Unix() - s.create + cnt := diff/s.every + 1 + return t.Add(time.Duration(cnt*s.every) * time.Second) + } + + // Start at the earliest possible time (the upcoming second). + t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond) + var ( + loc = t.Location() + added = false + yearLimit = t.Year() + 5 + ) + +WRAP: + if t.Year() > yearLimit { + return t // who will care the job that run in five years later + } + + for !match(s.month, int(t.Month())) { + if !added { + added = true + t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, loc) + } + t = t.AddDate(0, 1, 0) + // need recheck + if t.Month() == time.January { + goto WRAP + } + } + + for !s.dayMatches(t) { + if !added { + added = true + t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc) + } + t = t.AddDate(0, 0, 1) + + // Notice if the hour is no longer midnight due to DST. + // Add an hour if it's 23, subtract an hour if it's 1. + if t.Hour() != 0 { + if t.Hour() > 12 { + t = t.Add(time.Duration(24-t.Hour()) * time.Hour) + } else { + t = t.Add(time.Duration(-t.Hour()) * time.Hour) + } + } + if t.Day() == 1 { + goto WRAP + } + } + for !match(s.hour, t.Hour()) { + if !added { + added = true + t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, loc) + } + t = t.Add(time.Hour) + // need recheck + if t.Hour() == 0 { + goto WRAP + } + } + for !match(s.minute, t.Minute()) { + if !added { + added = true + t = t.Truncate(time.Minute) + } + t = t.Add(1 * time.Minute) + + if t.Minute() == 0 { + goto WRAP + } + } + for !match(s.second, t.Second()) { + if !added { + added = true + t = t.Truncate(time.Second) + } + t = t.Add(1 * time.Second) + if t.Second() == 0 { + goto WRAP + } + } + return t.In(loc) +} + +// dayMatches returns true if the schedule's day-of-week and day-of-month +// restrictions are satisfied by the given time. +func (s *cronSchedule) dayMatches(t time.Time) bool { + _, ok1 := s.day[t.Day()] + _, ok2 := s.week[int(t.Weekday())] + return ok1 && ok2 +} + +func match(m map[int]struct{}, key int) bool { + _, ok := m[key] + return ok +} diff --git a/os/gcron/gcron_z_unit_schedule_test.go b/os/gcron/gcron_z_unit_schedule_test.go new file mode 100644 index 000000000..aa4515616 --- /dev/null +++ b/os/gcron/gcron_z_unit_schedule_test.go @@ -0,0 +1,123 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gcron + +import ( + "strings" + "testing" + "time" + + "github.com/gogf/gf/v2/test/gtest" +) + +func TestSlash(t *testing.T) { + + runs := []struct { + spec string + expected map[int]struct{} + }{ + {"0 0 0 * Feb Mon/2", map[int]struct{}{1: struct{}{}, 3: struct{}{}, 5: struct{}{}}}, + {"0 0 0 * Feb *", map[int]struct{}{1: struct{}{}, 2: struct{}{}, 3: struct{}{}, 4: struct{}{}, 5: struct{}{}, 6: struct{}{}, 0: struct{}{}}}, + } + + gtest.C(t, func(t *gtest.T) { + for _, c := range runs { + sched, err := newSchedule(c.spec) + if err != nil { + t.Fatal(err) + + } + t.AssertEQ(sched.week, c.expected) + } + }) + +} + +func TestNext(t *testing.T) { + runs := []struct { + time, spec string + expected string + }{ + // Simple cases + {"Mon Jul 9 14:45 2012", "0 0/15 * * * *", "Mon Jul 9 15:00 2012"}, + {"Mon Jul 9 14:59 2012", "0 0/15 * * * *", "Mon Jul 9 15:00 2012"}, + {"Mon Jul 9 14:59:59 2012", "0 0/15 * * * *", "Mon Jul 9 15:00 2012"}, + + // Wrap around hours + {"Mon Jul 9 15:45 2012", "0 20-35/15 * * * *", "Mon Jul 9 16:20 2012"}, + + // Wrap around days + {"Mon Jul 9 23:46 2012", "0 */15 * * * *", "Tue Jul 10 00:00 2012"}, + {"Mon Jul 9 23:45 2012", "0 20-35/15 * * * *", "Tue Jul 10 00:20 2012"}, + {"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * * * *", "Tue Jul 10 00:20:15 2012"}, + {"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 1/2 * * *", "Tue Jul 10 01:20:15 2012"}, + {"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 10-12 * * *", "Tue Jul 10 10:20:15 2012"}, + + {"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 1/2 */2 * *", "Thu Jul 11 01:20:15 2012"}, + {"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * 9-20 * *", "Wed Jul 10 00:20:15 2012"}, + {"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * 9-20 Jul *", "Wed Jul 10 00:20:15 2012"}, + + // Wrap around months + {"Mon Jul 9 23:35 2012", "0 0 0 9 Apr-Oct ?", "Thu Aug 9 00:00 2012"}, + {"Mon Jul 9 23:35 2012", "0 0 0 */5 Apr,Aug,Oct Mon", "Mon Aug 6 00:00 2012"}, + {"Mon Jul 9 23:35 2012", "0 0 0 */5 Oct Mon", "Mon Oct 1 00:00 2012"}, + + // Wrap around years + {"Mon Jul 9 23:35 2012", "0 0 0 * Feb Mon", "Mon Feb 4 00:00 2013"}, + {"Mon Jul 9 23:35 2012", "0 0 0 * Feb Mon/2", "Fri Feb 1 00:00 2013"}, + + // Wrap around minute, hour, day, month, and year + {"Mon Dec 31 23:59:45 2012", "0 * * * * *", "Tue Jan 1 00:00:00 2013"}, + + // Leap year + {"Mon Jul 9 23:35 2012", "0 0 0 29 Feb ?", "Mon Feb 29 00:00 2016"}, + } + + for _, c := range runs { + sched, err := newSchedule(c.spec) + if err != nil { + t.Error(err) + continue + } + // fmt.Printf("%+v", sched) + actual := sched.Next(getTime(c.time)) + expected := getTime(c.expected) + if !(actual.Unix() == expected.Unix()) { + t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.spec, expected, actual) + } + } +} +func getTime(value string) time.Time { + if value == "" { + return time.Time{} + } + + var location = time.Local + if strings.HasPrefix(value, "TZ=") { + parts := strings.Fields(value) + loc, err := time.LoadLocation(parts[0][len("TZ="):]) + if err != nil { + panic("could not parse location:" + err.Error()) + } + location = loc + value = parts[1] + } + + var layouts = []string{ + "Mon Jan 2 15:04 2006", + "Mon Jan 2 15:04:05 2006", + } + for _, layout := range layouts { + if t, err := time.ParseInLocation(layout, value, location); err == nil { + return t + } + } + if t, err := time.ParseInLocation("2006-01-02T15:04:05-0700", value, location); err == nil { + return t + } + panic("could not parse time value " + value) +} diff --git a/os/gfile/gfile_z_exmaple_basic_test.go b/os/gfile/gfile_z_exmaple_basic_test.go new file mode 100644 index 000000000..9a9f12d96 --- /dev/null +++ b/os/gfile/gfile_z_exmaple_basic_test.go @@ -0,0 +1,554 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gfile_test + +import ( + "fmt" + "os" + + "github.com/gogf/gf/v2/os/gfile" +) + +func ExampleMkdir() { + // init + var ( + path = gfile.TempDir("gfile_example_basic_dir") + ) + + // Creates directory + gfile.Mkdir(path) + + // Check if directory exists + fmt.Println(gfile.IsDir(path)) + + // Output: + // true +} + +func ExampleCreate() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + dataByte = make([]byte, 50) + ) + // Check whether the file exists + isFile := gfile.IsFile(path) + + fmt.Println(isFile) + + // Creates file with given `path` recursively + fileHandle, _ := gfile.Create(path) + defer fileHandle.Close() + + // Write some content to file + n, _ := fileHandle.WriteString("hello goframe") + + // Check whether the file exists + isFile = gfile.IsFile(path) + + fmt.Println(isFile) + + // Reads len(b) bytes from the File + fileHandle.ReadAt(dataByte, 0) + + fmt.Println(string(dataByte[:n])) + + // Output: + // false + // true + // hello goframe +} + +func ExampleOpen() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + dataByte = make([]byte, 4096) + ) + // Open file or directory with READONLY model + file, _ := gfile.Open(path) + defer file.Close() + + // Read data + n, _ := file.Read(dataByte) + + fmt.Println(string(dataByte[:n])) + + // Output: + // hello goframe +} + +func ExampleOpenFile() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + dataByte = make([]byte, 4096) + ) + // Opens file/directory with custom `flag` and `perm` + // Create if file does not exist,it is created in a readable and writable mode,prem 0777 + openFile, _ := gfile.OpenFile(path, os.O_CREATE|os.O_RDWR, gfile.DefaultPermCopy) + defer openFile.Close() + + // Write some content to file + writeLength, _ := openFile.WriteString("hello goframe test open file") + + fmt.Println(writeLength) + + // Read data + n, _ := openFile.ReadAt(dataByte, 0) + + fmt.Println(string(dataByte[:n])) + + // Output: + // 28 + // hello goframe test open file +} + +func ExampleOpenWithFlag() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + dataByte = make([]byte, 4096) + ) + + // Opens file/directory with custom `flag` + // Create if file does not exist,it is created in a readable and writable mode with default `perm` is 0666 + openFile, _ := gfile.OpenWithFlag(path, os.O_CREATE|os.O_RDWR) + defer openFile.Close() + + // Write some content to file + writeLength, _ := openFile.WriteString("hello goframe test open file with flag") + + fmt.Println(writeLength) + + // Read data + n, _ := openFile.ReadAt(dataByte, 0) + + fmt.Println(string(dataByte[:n])) + + // Output: + // 38 + // hello goframe test open file with flag +} + +func ExampleJoin() { + // init + var ( + dirPath = gfile.TempDir("gfile_example_basic_dir") + filePath = "file1" + ) + + // Joins string array paths with file separator of current system. + joinString := gfile.Join(dirPath, filePath) + + fmt.Println(joinString) + + // Output: + // /tmp/gfile_example_basic_dir/file1 +} + +func ExampleExists() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + // Checks whether given `path` exist. + joinString := gfile.Exists(path) + + fmt.Println(joinString) + + // Output: + // true +} + +func ExampleIsDir() { + // init + var ( + path = gfile.TempDir("gfile_example_basic_dir") + filePath = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + // Checks whether given `path` a directory. + fmt.Println(gfile.IsDir(path)) + fmt.Println(gfile.IsDir(filePath)) + + // Output: + // true + // false +} + +func ExamplePwd() { + // Get absolute path of current working directory. + fmt.Println(gfile.Pwd()) + + // May Output: + // xxx/gf/os/gfile +} + +func ExampleChdir() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + // Get current working directory + fmt.Println(gfile.Pwd()) + + // Changes the current working directory to the named directory. + gfile.Chdir(path) + + // Get current working directory + fmt.Println(gfile.Pwd()) + + // May Output: + // xxx/gf/os/gfile + // /tmp/gfile_example_basic_dir/file1 +} + +func ExampleIsFile() { + // init + var ( + filePath = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + dirPath = gfile.TempDir("gfile_example_basic_dir") + ) + // Checks whether given `path` a file, which means it's not a directory. + fmt.Println(gfile.IsFile(filePath)) + fmt.Println(gfile.IsFile(dirPath)) + + // Output: + // true + // false +} + +func ExampleStat() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + // Get a FileInfo describing the named file. + stat, _ := gfile.Stat(path) + + fmt.Println(stat.Name()) + fmt.Println(stat.IsDir()) + fmt.Println(stat.Mode()) + fmt.Println(stat.ModTime()) + fmt.Println(stat.Size()) + fmt.Println(stat.Sys()) + + // May Output: + // file1 + // false + // -rwxr-xr-x + // 2021-12-02 11:01:27.261441694 +0800 CST + // &{16777220 33261 1 8597857090 501 20 0 [0 0 0 0] {1638414088 192363490} {1638414087 261441694} {1638414087 261441694} {1638413480 485068275} 38 8 4096 0 0 0 [0 0]} +} + +func ExampleMove() { + // init + var ( + srcPath = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + dstPath = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file2") + ) + // Check is file + fmt.Println(gfile.IsFile(dstPath)) + + // Moves `src` to `dst` path. + // If `dst` already exists and is not a directory, it'll be replaced. + gfile.Move(srcPath, dstPath) + + fmt.Println(gfile.IsFile(srcPath)) + fmt.Println(gfile.IsFile(dstPath)) + + // Output: + // false + // false + // true +} + +func ExampleRename() { + // init + var ( + srcPath = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file2") + dstPath = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + // Check is file + fmt.Println(gfile.IsFile(dstPath)) + + // renames (moves) `src` to `dst` path. + // If `dst` already exists and is not a directory, it'll be replaced. + gfile.Rename(srcPath, dstPath) + + fmt.Println(gfile.IsFile(srcPath)) + fmt.Println(gfile.IsFile(dstPath)) + + // Output: + // false + // false + // true +} + +func ExampleDirNames() { + // init + var ( + path = gfile.TempDir("gfile_example_basic_dir") + ) + // Get sub-file names of given directory `path`. + dirNames, _ := gfile.DirNames(path) + + fmt.Println(dirNames) + + // May Output: + // [file1] +} + +func ExampleGlob() { + // init + var ( + path = gfile.Pwd() + gfile.Separator + "*_example_basic_test.go" + ) + // Get sub-file names of given directory `path`. + // Only show file name + matchNames, _ := gfile.Glob(path, true) + + fmt.Println(matchNames) + + // Show full path of the file + matchNames, _ = gfile.Glob(path, false) + + fmt.Println(matchNames) + + // May Output: + // [gfile_z_example_basic_test.go] + // [xxx/gf/os/gfile/gfile_z_example_basic_test.go] +} + +func ExampleIsReadable() { + // init + var ( + path = gfile.Pwd() + gfile.Separator + "testdata/readline/file.log" + ) + + // Checks whether given `path` is readable. + fmt.Println(gfile.IsReadable(path)) + + // Output: + // true +} + +func ExampleIsWritable() { + // init + var ( + path = gfile.Pwd() + gfile.Separator + "testdata/readline/file.log" + ) + + // Checks whether given `path` is writable. + fmt.Println(gfile.IsWritable(path)) + + // Output: + // true +} + +func ExampleChmod() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + + // Get a FileInfo describing the named file. + stat, err := gfile.Stat(path) + if err != nil { + fmt.Println(err.Error()) + } + // Show original mode + fmt.Println(stat.Mode()) + + // Change file model + gfile.Chmod(path, gfile.DefaultPermCopy) + + // Get a FileInfo describing the named file. + stat, _ = gfile.Stat(path) + // Show the modified mode + fmt.Println(stat.Mode()) + + // Output: + // -rw-r--r-- + // -rwxrwxrwx +} + +func ExampleAbs() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + + // Get an absolute representation of path. + fmt.Println(gfile.Abs(path)) + + // Output: + // /tmp/gfile_example_basic_dir/file1 +} + +func ExampleRealPath() { + // init + var ( + realPath = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + worryPath = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "worryFile") + ) + + // fetch an absolute representation of path. + fmt.Println(gfile.RealPath(realPath)) + fmt.Println(gfile.RealPath(worryPath)) + + // Output: + // /tmp/gfile_example_basic_dir/file1 + // +} + +func ExampleSelfPath() { + + // Get absolute file path of current running process + fmt.Println(gfile.SelfPath()) + + // May Output: + // xxx/___github_com_gogf_gf_v2_os_gfile__ExampleSelfPath +} + +func ExampleSelfName() { + + // Get file name of current running process + fmt.Println(gfile.SelfName()) + + // May Output: + // ___github_com_gogf_gf_v2_os_gfile__ExampleSelfName +} + +func ExampleSelfDir() { + + // Get absolute directory path of current running process + fmt.Println(gfile.SelfDir()) + + // May Output: + // /private/var/folders/p6/gc_9mm3j229c0mjrjp01gqn80000gn/T +} + +func ExampleBasename() { + // init + var ( + path = gfile.Pwd() + gfile.Separator + "testdata/readline/file.log" + ) + + // Get the last element of path, which contains file extension. + fmt.Println(gfile.Basename(path)) + + // Output: + // file.log +} + +func ExampleName() { + // init + var ( + path = gfile.Pwd() + gfile.Separator + "testdata/readline/file.log" + ) + + // Get the last element of path without file extension. + fmt.Println(gfile.Name(path)) + + // Output: + // file +} + +func ExampleDir() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + + // Get all but the last element of path, typically the path's directory. + fmt.Println(gfile.Dir(path)) + + // Output: + // /tmp/gfile_example_basic_dir +} + +func ExampleIsEmpty() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + + // Check whether the `path` is empty + fmt.Println(gfile.IsEmpty(path)) + + // Truncate file + gfile.Truncate(path, 0) + + // Check whether the `path` is empty + fmt.Println(gfile.IsEmpty(path)) + + // Output: + // false + // true +} + +func ExampleExt() { + // init + var ( + path = gfile.Pwd() + gfile.Separator + "testdata/readline/file.log" + ) + + // Get the file name extension used by path. + fmt.Println(gfile.Ext(path)) + + // Output: + // .log +} + +func ExampleExtName() { + // init + var ( + path = gfile.Pwd() + gfile.Separator + "testdata/readline/file.log" + ) + + // Get the file name extension used by path but the result does not contains symbol '.'. + fmt.Println(gfile.ExtName(path)) + + // Output: + // log +} + +func ExampleTempDir() { + // init + var ( + fileName = "gfile_example_basic_dir" + ) + + // fetch an absolute representation of path. + path := gfile.TempDir(fileName) + + fmt.Println(path) + + // Output: + // /tmp/gfile_example_basic_dir +} + +func ExampleRemove() { + // init + var ( + path = gfile.Join(gfile.TempDir("gfile_example_basic_dir"), "file1") + ) + + // Checks whether given `path` a file, which means it's not a directory. + fmt.Println(gfile.IsFile(path)) + + // deletes all file/directory with `path` parameter. + gfile.Remove(path) + + // Check again + fmt.Println(gfile.IsFile(path)) + + // Output: + // true + // false +} diff --git a/os/gspath/gspath.go b/os/gspath/gspath.go index e0a986cfc..f036b75d3 100644 --- a/os/gspath/gspath.go +++ b/os/gspath/gspath.go @@ -205,7 +205,7 @@ func (sp *SPath) Search(name string, indexFiles ...string) (filePath string, isD name = "" } for _, file := range indexFiles { - if v := sp.cache.Get(name + "/" + file); v != "" { + if v = sp.cache.Get(name + "/" + file); v != "" { return sp.parseCacheValue(v) } } diff --git a/os/gtime/gtime_z_example_time_test.go b/os/gtime/gtime_z_example_time_test.go index 0ac899256..06f139334 100644 --- a/os/gtime/gtime_z_example_time_test.go +++ b/os/gtime/gtime_z_example_time_test.go @@ -7,6 +7,7 @@ package gtime_test import ( + "encoding/json" "fmt" "reflect" "time" @@ -467,11 +468,31 @@ func ExampleTime_EndOfYear() { } func ExampleTime_MarshalJSON() { - gt1 := gtime.New("2018-08-08 08:08:08") - - json, _ := gt1.MarshalJSON() - fmt.Println(string(json)) + type Person struct { + Name string `json:"name"` + Birthday *gtime.Time `json:"birthday"` + } + p := new(Person) + p.Name = "goframe" + p.Birthday = gtime.New("2018-08-08 08:08:08") + j, _ := json.Marshal(p) + fmt.Println(string(j)) // Output: - // "2018-08-08 08:08:08" + // {"name":"goframe","birthday":"2018-08-08 08:08:08"} +} + +func ExampleTime_UnmarshalJSON() { + type Person struct { + Name string `json:"name"` + Birthday *gtime.Time `json:"birthday"` + } + p := new(Person) + src := `{"name":"goframe","birthday":"2018-08-08 08:08:08"}` + json.Unmarshal([]byte(src), p) + + fmt.Println(p) + + // Output + // &{goframe 2018-08-08 08:08:08} } diff --git a/util/gvalid/gvalid_validator_check_value.go b/util/gvalid/gvalid_validator_check_value.go index 4635d5068..5bb9cb854 100644 --- a/util/gvalid/gvalid_validator_check_value.go +++ b/util/gvalid/gvalid_validator_check_value.go @@ -80,7 +80,7 @@ func (v *Validator) doCheckValue(ctx context.Context, in doCheckValueInput) Erro } else { return newValidationErrorByStr( internalRulesErrRuleName, - errors.New(internalRulesErrRuleName+": "+in.Rule), + errors.New(internalRulesErrRuleName+": "+ruleItems[i]), ) } } else { diff --git a/util/gvalid/gvalid_z_example_test.go b/util/gvalid/gvalid_z_example_test.go index 127e320ad..3ae647821 100644 --- a/util/gvalid/gvalid_z_example_test.go +++ b/util/gvalid/gvalid_z_example_test.go @@ -391,7 +391,7 @@ func ExampleCheckStruct() { Page: 1, Size: 10, } - err := g.Validator().Data(obj).Rules(nil).Run(gctx.New()) + err := g.Validator().Data(obj).Run(gctx.New()) fmt.Println(err == nil) // Output: // true @@ -408,7 +408,7 @@ func ExampleCheckStruct2() { Page: 1, Size: 10, } - err := g.Validator().Data(obj).Rules(nil).Run(gctx.New()) + err := g.Validator().Data(obj).Run(gctx.New()) fmt.Println(err == nil) // Output: // true @@ -425,7 +425,7 @@ func ExampleCheckStruct3() { Page: 1, Size: 10, } - err := g.Validator().Data(obj).Rules(nil).Run(gctx.New()) + err := g.Validator().Data(obj).Run(gctx.New()) fmt.Println(err) // Output: // project id must between 1, 10000 @@ -458,7 +458,7 @@ func ExampleRegisterRule() { } return nil }) - err := g.Validator().Data(user).Rules(nil).Run(gctx.New()) + err := g.Validator().Data(user).Run(gctx.New()) fmt.Println(err.Error()) // May Output: // 用户名称已被占用 diff --git a/util/gvalid/gvalid_z_unit_feature_checkmap_test.go b/util/gvalid/gvalid_z_unit_feature_checkmap_test.go index 0d3c6afd7..9cdb0d4ba 100755 --- a/util/gvalid/gvalid_z_unit_feature_checkmap_test.go +++ b/util/gvalid/gvalid_z_unit_feature_checkmap_test.go @@ -39,7 +39,7 @@ func Test_CheckMap1(t *testing.T) { func Test_CheckMap2(t *testing.T) { var params interface{} gtest.C(t, func(t *gtest.T) { - if err := g.Validator().Data(params).Rules(nil).Messages(nil).Run(context.TODO()); err == nil { + if err := g.Validator().Data(params).Run(context.TODO()); err == nil { t.Assert(err, nil) } }) diff --git a/util/gvalid/gvalid_z_unit_feature_checkstruct_test.go b/util/gvalid/gvalid_z_unit_feature_checkstruct_test.go index 82b35f1ab..237938d99 100755 --- a/util/gvalid/gvalid_z_unit_feature_checkstruct_test.go +++ b/util/gvalid/gvalid_z_unit_feature_checkstruct_test.go @@ -119,7 +119,7 @@ func Test_CheckStruct(t *testing.T) { Password string `json:"password" gvalid:"password@required#登录密码不能为空"` } var login LoginRequest - err := g.Validator().Data(login).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(login).Run(context.TODO()) t.AssertNE(err, nil) t.Assert(len(err.Maps()), 2) t.Assert(err.Maps()["username"]["required"], "用户名不能为空") @@ -132,7 +132,7 @@ func Test_CheckStruct(t *testing.T) { Password string `json:"password" gvalid:"@required#登录密码不能为空"` } var login LoginRequest - err := g.Validator().Data(login).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(login).Run(context.TODO()) t.Assert(err, nil) }) @@ -142,7 +142,7 @@ func Test_CheckStruct(t *testing.T) { Password string `json:"password" gvalid:"password@required#登录密码不能为空"` } var login LoginRequest - err := g.Validator().Data(login).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(login).Run(context.TODO()) t.AssertNE(err, nil) t.Assert(err.Maps()["password"]["required"], "登录密码不能为空") }) @@ -160,7 +160,7 @@ func Test_CheckStruct(t *testing.T) { Username: "john", Password: "123456", } - err := g.Validator().Data(user).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(user).Run(context.TODO()) t.AssertNE(err, nil) t.Assert(len(err.Maps()), 1) t.Assert(err.Maps()["uid"]["min"], "ID不能为空") @@ -201,7 +201,7 @@ func Test_CheckStruct(t *testing.T) { Username: "john", Password: "123456", } - err := g.Validator().Data(user).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(user).Run(context.TODO()) t.AssertNE(err, nil) t.Assert(len(err.Maps()), 1) }) @@ -219,7 +219,7 @@ func Test_CheckStruct(t *testing.T) { Username: "john", Password: "123456", } - err := g.Validator().Data(user).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(user).Run(context.TODO()) t.AssertNE(err, nil) t.Assert(len(err.Maps()), 1) t.Assert(err.Maps()["uid"]["min"], "ID不能为空") @@ -295,7 +295,7 @@ func Test_CheckStruct_With_EmbeddedObject(t *testing.T) { Pass2: "2", }, } - err := g.Validator().Data(user).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(user).Run(context.TODO()) t.AssertNE(err, nil) t.Assert(err.Maps()["name"], g.Map{"required": "请输入您的姓名"}) t.Assert(err.Maps()["password1"], g.Map{"same": "您两次输入的密码不一致"}) @@ -321,7 +321,7 @@ func Test_CheckStruct_With_StructAttribute(t *testing.T) { Pass2: "2", }, } - err := g.Validator().Data(user).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(user).Run(context.TODO()) t.AssertNE(err, nil) t.Assert(err.Maps()["name"], g.Map{"required": "请输入您的姓名"}) t.Assert(err.Maps()["password1"], g.Map{"same": "您两次输入的密码不一致"}) @@ -340,7 +340,7 @@ func Test_CheckStruct_Optional(t *testing.T) { Page: 1, Size: 10, } - err := g.Validator().Data(obj).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(obj).Run(context.TODO()) t.Assert(err, nil) }) gtest.C(t, func(t *gtest.T) { @@ -353,7 +353,7 @@ func Test_CheckStruct_Optional(t *testing.T) { Page: 1, Size: 10, } - err := g.Validator().Data(obj).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(obj).Run(context.TODO()) t.Assert(err, nil) }) gtest.C(t, func(t *gtest.T) { @@ -366,7 +366,7 @@ func Test_CheckStruct_Optional(t *testing.T) { Page: 1, Size: 10, } - err := g.Validator().Data(obj).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(obj).Run(context.TODO()) t.Assert(err.String(), "project id must between 1, 10000") }) } @@ -382,7 +382,7 @@ func Test_CheckStruct_NoTag(t *testing.T) { Page: 1, Size: 10, } - err := g.Validator().Data(obj).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(obj).Run(context.TODO()) t.Assert(err, nil) }) } @@ -399,7 +399,7 @@ func Test_CheckStruct_InvalidRule(t *testing.T) { Age: 18, Phone: "123", } - err := g.Validator().Data(obj).Rules(nil).Run(context.TODO()) + err := g.Validator().Data(obj).Run(context.TODO()) t.AssertNE(err, nil) }) } diff --git a/util/gvalid/gvalid_z_unit_feature_ci_test.go b/util/gvalid/gvalid_z_unit_feature_ci_test.go index 514fbb5e0..fcacf15c1 100644 --- a/util/gvalid/gvalid_z_unit_feature_ci_test.go +++ b/util/gvalid/gvalid_z_unit_feature_ci_test.go @@ -15,11 +15,11 @@ import ( func Test_CI(t *testing.T) { gtest.C(t, func(t *gtest.T) { - err := g.Validator().Data("id").Rules("in:Id,Name").Messages(nil).Run(ctx) + err := g.Validator().Data("id").Rules("in:Id,Name").Run(ctx) t.AssertNE(err, nil) }) gtest.C(t, func(t *gtest.T) { - err := g.Validator().Data("id").Rules("ci|in:Id,Name").Messages(nil).Run(ctx) + err := g.Validator().Data("id").Rules("ci|in:Id,Name").Run(ctx) t.AssertNil(err) }) gtest.C(t, func(t *gtest.T) { diff --git a/util/gvalid/gvalid_z_unit_feature_custom_error_test.go b/util/gvalid/gvalid_z_unit_feature_custom_error_test.go index c27591207..7b333febe 100755 --- a/util/gvalid/gvalid_z_unit_feature_custom_error_test.go +++ b/util/gvalid/gvalid_z_unit_feature_custom_error_test.go @@ -20,7 +20,7 @@ func Test_Map(t *testing.T) { var ( rule = "ipv4" val = "0.0.0" - err = g.Validator().Data(val).Rules(rule).Messages(nil).Run(context.TODO()) + err = g.Validator().Data(val).Rules(rule).Run(context.TODO()) msg = map[string]string{ "ipv4": "The value `0.0.0` is not a valid IPv4 address", } @@ -34,7 +34,7 @@ func Test_FirstString(t *testing.T) { var ( rule = "ipv4" val = "0.0.0" - err = g.Validator().Data(val).Rules(rule).Messages(nil).Run(context.TODO()) + err = g.Validator().Data(val).Rules(rule).Run(context.TODO()) ) t.Assert(err.FirstError(), "The value `0.0.0` is not a valid IPv4 address") }) diff --git a/util/gvalid/gvalid_z_unit_feature_custom_rule_test.go b/util/gvalid/gvalid_z_unit_feature_custom_rule_test.go index 717261404..360804602 100644 --- a/util/gvalid/gvalid_z_unit_feature_custom_rule_test.go +++ b/util/gvalid/gvalid_z_unit_feature_custom_rule_test.go @@ -49,7 +49,7 @@ func Test_CustomRule1(t *testing.T) { Value: "123", Data: "123456", } - err := g.Validator().Data(st).Rules(nil).Run(ctx) + err := g.Validator().Data(st).Run(ctx) t.Assert(err.String(), "自定义错误") }) // No error with struct validation. @@ -62,7 +62,7 @@ func Test_CustomRule1(t *testing.T) { Value: "123456", Data: "123456", } - err := g.Validator().Data(st).Rules(nil).Run(ctx) + err := g.Validator().Data(st).Run(ctx) t.Assert(err, nil) }) } @@ -92,7 +92,7 @@ func Test_CustomRule2(t *testing.T) { Value: map[string]string{}, Data: "123456", } - err := g.Validator().Data(st).Rules(nil).Run(ctx) + err := g.Validator().Data(st).Run(ctx) t.Assert(err.String(), "自定义错误") }) // No error with struct validation. @@ -105,7 +105,7 @@ func Test_CustomRule2(t *testing.T) { Value: map[string]string{"k": "v"}, Data: "123456", } - err := g.Validator().Data(st).Rules(nil).Run(ctx) + err := g.Validator().Data(st).Run(ctx) t.Assert(err, nil) }) } @@ -136,7 +136,7 @@ func Test_CustomRule_AllowEmpty(t *testing.T) { Value: "", Data: "123456", } - err := g.Validator().Data(st).Rules(nil).Run(ctx) + err := g.Validator().Data(st).Run(ctx) t.Assert(err, nil) }) // No error with struct validation. @@ -149,7 +149,7 @@ func Test_CustomRule_AllowEmpty(t *testing.T) { Value: "john", Data: "123456", } - err := g.Validator().Data(st).Rules(nil).Run(ctx) + err := g.Validator().Data(st).Run(ctx) t.Assert(err.String(), "自定义错误") }) } diff --git a/util/gvalid/gvalid_z_unit_feature_recursive_test.go b/util/gvalid/gvalid_z_unit_feature_recursive_test.go index e71d3cf1b..b441f7c70 100755 --- a/util/gvalid/gvalid_z_unit_feature_recursive_test.go +++ b/util/gvalid/gvalid_z_unit_feature_recursive_test.go @@ -91,7 +91,7 @@ func Test_CheckStruct_Recursive_SliceStruct(t *testing.T) { }, }, } - err := g.Validator().Data(user).Rules(nil).Run(ctx) + err := g.Validator().Data(user).Run(ctx) g.Dump(err.Items()) t.AssertNE(err, nil) t.Assert(err.Maps()["Name"], g.Map{"required": "The Name field is required"}) @@ -145,7 +145,7 @@ func Test_CheckStruct_Recursive_SliceStruct_Required(t *testing.T) { Passes []Pass } user := &User{} - err := g.Validator().Data(user).Rules(nil).Run(ctx) + err := g.Validator().Data(user).Run(ctx) g.Dump(err.Items()) t.AssertNE(err, nil) t.Assert(err.Maps()["Name"], g.Map{"required": "The Name field is required"}) @@ -178,7 +178,7 @@ func Test_CheckStruct_Recursive_MapStruct(t *testing.T) { }, }, } - err := g.Validator().Data(user).Rules(nil).Run(ctx) + err := g.Validator().Data(user).Run(ctx) g.Dump(err.Items()) t.AssertNE(err, nil) t.Assert(err.Maps()["Name"], g.Map{"required": "The Name field is required"}) diff --git a/util/gvalid/gvalid_z_unit_feature_rule_test.go b/util/gvalid/gvalid_z_unit_feature_rule_test.go index 9aef7a934..f249ed73b 100755 --- a/util/gvalid/gvalid_z_unit_feature_rule_test.go +++ b/util/gvalid/gvalid_z_unit_feature_rule_test.go @@ -28,9 +28,9 @@ func Test_Check(t *testing.T) { val1 := 0 val2 := 7 val3 := 20 - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) t.Assert(err1, "InvalidRules: abc:6,16") t.Assert(err2, "InvalidRules: abc:6,16") t.Assert(err3, "InvalidRules: abc:6,16") @@ -38,16 +38,16 @@ func Test_Check(t *testing.T) { } func Test_Required(t *testing.T) { - if m := g.Validator().Data("1").Rules("required").Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("1").Rules("required").Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("").Rules("required").Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("").Rules("required").Run(ctx); m == nil { t.Error(m) } - if m := g.Validator().Data("").Assoc(map[string]interface{}{"id": 1, "age": 19}).Rules("required-if: id,1,age,18").Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("").Assoc(map[string]interface{}{"id": 1, "age": 19}).Rules("required-if: id,1,age,18").Run(ctx); m == nil { t.Error("Required校验失败") } - if m := g.Validator().Data("").Assoc(map[string]interface{}{"id": 2, "age": 19}).Rules("required-if: id,1,age,18").Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("").Assoc(map[string]interface{}{"id": 2, "age": 19}).Rules("required-if: id,1,age,18").Run(ctx); m != nil { t.Error("Required校验失败") } } @@ -55,20 +55,20 @@ func Test_Required(t *testing.T) { func Test_RequiredIf(t *testing.T) { gtest.C(t, func(t *gtest.T) { rule := "required-if:id,1,age,18" - t.AssertNE(g.Validator().Data("").Assoc(g.Map{"id": 1}).Rules(rule).Messages(nil).Run(ctx), nil) - t.Assert(g.Validator().Data("").Assoc(g.Map{"id": 0}).Rules(rule).Messages(nil).Run(ctx), nil) - t.AssertNE(g.Validator().Data("").Assoc(g.Map{"age": 18}).Rules(rule).Messages(nil).Run(ctx), nil) - t.Assert(g.Validator().Data("").Assoc(g.Map{"age": 20}).Rules(rule).Messages(nil).Run(ctx), nil) + t.AssertNE(g.Validator().Data("").Assoc(g.Map{"id": 1}).Rules(rule).Run(ctx), nil) + t.Assert(g.Validator().Data("").Assoc(g.Map{"id": 0}).Rules(rule).Run(ctx), nil) + t.AssertNE(g.Validator().Data("").Assoc(g.Map{"age": 18}).Rules(rule).Run(ctx), nil) + t.Assert(g.Validator().Data("").Assoc(g.Map{"age": 20}).Rules(rule).Run(ctx), nil) }) } func Test_RequiredUnless(t *testing.T) { gtest.C(t, func(t *gtest.T) { rule := "required-unless:id,1,age,18" - t.Assert(g.Validator().Data("").Assoc(g.Map{"id": 1}).Rules(rule).Messages(nil).Run(ctx), nil) - t.AssertNE(g.Validator().Data("").Assoc(g.Map{"id": 0}).Rules(rule).Messages(nil).Run(ctx), nil) - t.Assert(g.Validator().Data("").Assoc(g.Map{"age": 18}).Rules(rule).Messages(nil).Run(ctx), nil) - t.AssertNE(g.Validator().Data("").Assoc(g.Map{"age": 20}).Rules(rule).Messages(nil).Run(ctx), nil) + t.Assert(g.Validator().Data("").Assoc(g.Map{"id": 1}).Rules(rule).Run(ctx), nil) + t.AssertNE(g.Validator().Data("").Assoc(g.Map{"id": 0}).Rules(rule).Run(ctx), nil) + t.Assert(g.Validator().Data("").Assoc(g.Map{"age": 18}).Rules(rule).Run(ctx), nil) + t.AssertNE(g.Validator().Data("").Assoc(g.Map{"age": 20}).Rules(rule).Run(ctx), nil) }) } @@ -86,9 +86,9 @@ func Test_RequiredWith(t *testing.T) { "id": 100, "name": "john", } - err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Run(ctx) t.Assert(err1, nil) t.AssertNE(err2, nil) t.AssertNE(err3, nil) @@ -106,9 +106,9 @@ func Test_RequiredWith(t *testing.T) { params3 := g.Map{ "time": time.Time{}, } - err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Run(ctx) t.Assert(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -125,9 +125,9 @@ func Test_RequiredWith(t *testing.T) { params3 := g.Map{ "time": time.Now(), } - err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Run(ctx) t.Assert(err1, nil) t.AssertNE(err2, nil) t.AssertNE(err3, nil) @@ -175,9 +175,9 @@ func Test_RequiredWithAll(t *testing.T) { "id": 100, "name": "john", } - err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Run(ctx) t.Assert(err1, nil) t.Assert(err2, nil) t.AssertNE(err3, nil) @@ -198,9 +198,9 @@ func Test_RequiredWithOut(t *testing.T) { "id": 100, "name": "john", } - err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -221,9 +221,9 @@ func Test_RequiredWithOutAll(t *testing.T) { "id": 100, "name": "john", } - err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -241,14 +241,14 @@ func Test_Date(t *testing.T) { val6 := "2010/11/01" val7 := "2010=11=01" val8 := "123" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) - err6 := g.Validator().Data(val6).Rules(rule).Messages(nil).Run(ctx) - err7 := g.Validator().Data(val7).Rules(rule).Messages(nil).Run(ctx) - err8 := g.Validator().Data(val8).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) + err6 := g.Validator().Data(val6).Rules(rule).Run(ctx) + err7 := g.Validator().Data(val7).Rules(rule).Run(ctx) + err8 := g.Validator().Data(val8).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -289,12 +289,12 @@ func Test_DateFormat(t *testing.T) { val4 := "201011-01" val5 := "2010~11~01" val6 := "2010-11~01" - err1 := g.Validator().Data(val1).Rules("date-format:Y").Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules("date-format:Ym").Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules("date-format:Y.m").Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules("date-format:Ym-d").Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules("date-format:Y~m~d").Messages(nil).Run(ctx) - err6 := g.Validator().Data(val6).Rules("date-format:Y~m~d").Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules("date-format:Y").Run(ctx) + err2 := g.Validator().Data(val2).Rules("date-format:Ym").Run(ctx) + err3 := g.Validator().Data(val3).Rules("date-format:Y.m").Run(ctx) + err4 := g.Validator().Data(val4).Rules("date-format:Ym-d").Run(ctx) + err5 := g.Validator().Data(val5).Rules("date-format:Y~m~d").Run(ctx) + err6 := g.Validator().Data(val6).Rules("date-format:Y~m~d").Run(ctx) t.Assert(err1, nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -319,10 +319,10 @@ func Test_Email(t *testing.T) { value2 := "m@www@johngcn" value3 := "m-m_m@mail.johng.cn" value4 := "m.m-m@johng.cn" - err1 := g.Validator().Data(value1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(value2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(value3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(value4).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(value1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(value2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(value3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(value4).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -332,10 +332,10 @@ func Test_Email(t *testing.T) { func Test_Phone(t *testing.T) { gtest.C(t, func(t *gtest.T) { - err1 := g.Validator().Data("1361990897").Rules("phone").Messages(nil).Run(ctx) - err2 := g.Validator().Data("13619908979").Rules("phone").Messages(nil).Run(ctx) - err3 := g.Validator().Data("16719908979").Rules("phone").Messages(nil).Run(ctx) - err4 := g.Validator().Data("19719908989").Rules("phone").Messages(nil).Run(ctx) + err1 := g.Validator().Data("1361990897").Rules("phone").Run(ctx) + err2 := g.Validator().Data("13619908979").Rules("phone").Run(ctx) + err3 := g.Validator().Data("16719908979").Rules("phone").Run(ctx) + err4 := g.Validator().Data("19719908989").Rules("phone").Run(ctx) t.AssertNE(err1.String(), nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -345,12 +345,12 @@ func Test_Phone(t *testing.T) { func Test_PhoneLoose(t *testing.T) { gtest.C(t, func(t *gtest.T) { - err1 := g.Validator().Data("13333333333").Rules("phone-loose").Messages(nil).Run(ctx) - err2 := g.Validator().Data("15555555555").Rules("phone-loose").Messages(nil).Run(ctx) - err3 := g.Validator().Data("16666666666").Rules("phone-loose").Messages(nil).Run(ctx) - err4 := g.Validator().Data("23333333333").Rules("phone-loose").Messages(nil).Run(ctx) - err5 := g.Validator().Data("1333333333").Rules("phone-loose").Messages(nil).Run(ctx) - err6 := g.Validator().Data("10333333333").Rules("phone-loose").Messages(nil).Run(ctx) + err1 := g.Validator().Data("13333333333").Rules("phone-loose").Run(ctx) + err2 := g.Validator().Data("15555555555").Rules("phone-loose").Run(ctx) + err3 := g.Validator().Data("16666666666").Rules("phone-loose").Run(ctx) + err4 := g.Validator().Data("23333333333").Rules("phone-loose").Run(ctx) + err5 := g.Validator().Data("1333333333").Rules("phone-loose").Run(ctx) + err6 := g.Validator().Data("10333333333").Rules("phone-loose").Run(ctx) t.Assert(err1, nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -368,11 +368,11 @@ func Test_Telephone(t *testing.T) { val3 := "86292651" val4 := "028-8692651" val5 := "0830-8692651" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -389,11 +389,11 @@ func Test_Passport(t *testing.T) { val3 := "aaaaa" val4 := "aaaaaa" val5 := "a123_456" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.AssertNE(err3, nil) @@ -410,11 +410,11 @@ func Test_Password(t *testing.T) { val3 := "a12345-6" val4 := ">,/;'[09-" val5 := "a123_456" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -433,13 +433,13 @@ func Test_Password2(t *testing.T) { val5 := "a123_456" val6 := "Nant1986" val7 := "Nant1986!" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) - err6 := g.Validator().Data(val6).Rules(rule).Messages(nil).Run(ctx) - err7 := g.Validator().Data(val7).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) + err6 := g.Validator().Data(val6).Rules(rule).Run(ctx) + err7 := g.Validator().Data(val7).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.AssertNE(err3, nil) @@ -460,13 +460,13 @@ func Test_Password3(t *testing.T) { val5 := "a123_456" val6 := "Nant1986" val7 := "Nant1986!" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) - err6 := g.Validator().Data(val6).Rules(rule).Messages(nil).Run(ctx) - err7 := g.Validator().Data(val7).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) + err6 := g.Validator().Data(val6).Rules(rule).Run(ctx) + err7 := g.Validator().Data(val7).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.AssertNE(err3, nil) @@ -482,8 +482,8 @@ func Test_Postcode(t *testing.T) { rule := "postcode" val1 := "12345" val2 := "610036" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.Assert(err2, nil) }) @@ -497,11 +497,11 @@ func Test_ResidentId(t *testing.T) { val3 := "311128500121201" val4 := "510521198607185367" val5 := "51052119860718536x" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.AssertNE(err3, nil) @@ -515,8 +515,8 @@ func Test_BankCard(t *testing.T) { rule := "bank-card" val1 := "6230514630000424470" val2 := "6230514630000424473" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.Assert(err2, nil) }) @@ -530,11 +530,11 @@ func Test_QQ(t *testing.T) { val3 := "10000" val4 := "38996181" val5 := "389961817" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -544,31 +544,31 @@ func Test_QQ(t *testing.T) { } func Test_Ip(t *testing.T) { - if m := g.Validator().Data("10.0.0.1").Rules("ip").Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("10.0.0.1").Rules("ip").Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("10.0.0.1").Rules("ipv4").Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("10.0.0.1").Rules("ipv4").Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("0.0.0.0").Rules("ipv4").Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("0.0.0.0").Rules("ipv4").Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("1920.0.0.0").Rules("ipv4").Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("1920.0.0.0").Rules("ipv4").Run(ctx); m == nil { t.Error("ipv4校验失败") } - if m := g.Validator().Data("1920.0.0.0").Rules("ip").Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("1920.0.0.0").Rules("ip").Run(ctx); m == nil { t.Error("ipv4校验失败") } - if m := g.Validator().Data("fe80::5484:7aff:fefe:9799").Rules("ipv6").Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("fe80::5484:7aff:fefe:9799").Rules("ipv6").Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("fe80::5484:7aff:fefe:9799123").Rules("ipv6").Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("fe80::5484:7aff:fefe:9799123").Rules("ipv6").Run(ctx); m == nil { t.Error(m) } - if m := g.Validator().Data("fe80::5484:7aff:fefe:9799").Rules("ip").Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("fe80::5484:7aff:fefe:9799").Rules("ip").Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("fe80::5484:7aff:fefe:9799123").Rules("ip").Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("fe80::5484:7aff:fefe:9799123").Rules("ip").Run(ctx); m == nil { t.Error(m) } } @@ -581,11 +581,11 @@ func Test_IPv4(t *testing.T) { val3 := "1.1.1.1" val4 := "255.255.255.0" val5 := "127.0.0.1" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -602,11 +602,11 @@ func Test_IPv6(t *testing.T) { val3 := "1030::C9B4:FF12:48AA:1A2B" val4 := "2000:0:0:0:0:0:0:1" val5 := "0000:0000:0000:0000:0000:ffff:c0a8:5909" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -621,9 +621,9 @@ func Test_MAC(t *testing.T) { val1 := "192.168.1.1" val2 := "44-45-53-54-00-00" val3 := "01:00:5e:00:00:00" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -637,10 +637,10 @@ func Test_URL(t *testing.T) { val2 := "https://www.baidu.com" val3 := "http://127.0.0.1" val4 := "file:///tmp/test.txt" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -667,7 +667,7 @@ func Test_Domain(t *testing.T) { } var err error for k, v := range m { - err = g.Validator().Data(k).Rules("domain").Messages(nil).Run(ctx) + err = g.Validator().Data(k).Rules("domain").Run(ctx) if v { // fmt.Println(k) t.Assert(err, nil) @@ -681,10 +681,10 @@ func Test_Domain(t *testing.T) { func Test_Length(t *testing.T) { rule := "length:6,16" - if m := g.Validator().Data("123456").Rules(rule).Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("123456").Rules(rule).Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("12345").Rules(rule).Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("12345").Rules(rule).Run(ctx); m == nil { t.Error("长度校验失败") } } @@ -694,10 +694,10 @@ func Test_MinLength(t *testing.T) { msgs := map[string]string{ "min-length": "地址长度至少为{min}位", } - if m := g.Validator().Data("123456").Rules(rule).Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("123456").Rules(rule).Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("12345").Rules(rule).Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("12345").Rules(rule).Run(ctx); m == nil { t.Error("长度校验失败") } if m := g.Validator().Data("12345").Rules(rule).Messages(msgs).Run(ctx); m == nil { @@ -705,7 +705,7 @@ func Test_MinLength(t *testing.T) { } rule2 := "min-length:abc" - if m := g.Validator().Data("123456").Rules(rule2).Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("123456").Rules(rule2).Run(ctx); m == nil { t.Error("长度校验失败") } } @@ -715,10 +715,10 @@ func Test_MaxLength(t *testing.T) { msgs := map[string]string{ "max-length": "地址长度至大为{max}位", } - if m := g.Validator().Data("12345").Rules(rule).Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("12345").Rules(rule).Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("1234567").Rules(rule).Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("1234567").Rules(rule).Run(ctx); m == nil { t.Error("长度校验失败") } if m := g.Validator().Data("1234567").Rules(rule).Messages(msgs).Run(ctx); m == nil { @@ -726,30 +726,30 @@ func Test_MaxLength(t *testing.T) { } rule2 := "max-length:abc" - if m := g.Validator().Data("123456").Rules(rule2).Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("123456").Rules(rule2).Run(ctx); m == nil { t.Error("长度校验失败") } } func Test_Size(t *testing.T) { rule := "size:5" - if m := g.Validator().Data("12345").Rules(rule).Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("12345").Rules(rule).Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("123456").Rules(rule).Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("123456").Rules(rule).Run(ctx); m == nil { t.Error("长度校验失败") } } func Test_Between(t *testing.T) { rule := "between:6.01, 10.01" - if m := g.Validator().Data(10).Rules(rule).Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data(10).Rules(rule).Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data(10.02).Rules(rule).Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data(10.02).Rules(rule).Run(ctx); m == nil { t.Error("大小范围校验失败") } - if m := g.Validator().Data("a").Rules(rule).Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("a").Rules(rule).Run(ctx); m == nil { t.Error("大小范围校验失败") } } @@ -762,11 +762,11 @@ func Test_Min(t *testing.T) { val3 := "100" val4 := "1000" val5 := "a" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -774,7 +774,7 @@ func Test_Min(t *testing.T) { t.AssertNE(err5, nil) rule2 := "min:a" - err6 := g.Validator().Data(val1).Rules(rule2).Messages(nil).Run(ctx) + err6 := g.Validator().Data(val1).Rules(rule2).Run(ctx) t.AssertNE(err6, nil) }) } @@ -787,11 +787,11 @@ func Test_Max(t *testing.T) { val3 := "100" val4 := "1000" val5 := "a" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) t.Assert(err1, nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -799,7 +799,7 @@ func Test_Max(t *testing.T) { t.AssertNE(err5, nil) rule2 := "max:a" - err6 := g.Validator().Data(val1).Rules(rule2).Messages(nil).Run(ctx) + err6 := g.Validator().Data(val1).Rules(rule2).Run(ctx) t.AssertNE(err6, nil) }) } @@ -813,12 +813,12 @@ func Test_Json(t *testing.T) { val4 := "[]" val5 := "[1,2,3,4]" val6 := `{"list":[1,2,3,4]}` - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) - err6 := g.Validator().Data(val6).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) + err6 := g.Validator().Data(val6).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -837,12 +837,12 @@ func Test_Integer(t *testing.T) { val4 := "1" val5 := "100" val6 := `999999999` - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) - err6 := g.Validator().Data(val6).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) + err6 := g.Validator().Data(val6).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -861,12 +861,12 @@ func Test_Float(t *testing.T) { val4 := "1.0" val5 := "1.1" val6 := `0.1` - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) - err6 := g.Validator().Data(val6).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) + err6 := g.Validator().Data(val6).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -885,12 +885,12 @@ func Test_Boolean(t *testing.T) { val4 := "1" val5 := "true" val6 := `off` - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) - err5 := g.Validator().Data(val5).Rules(rule).Messages(nil).Run(ctx) - err6 := g.Validator().Data(val6).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) + err5 := g.Validator().Data(val5).Rules(rule).Run(ctx) + err6 := g.Validator().Data(val6).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -914,9 +914,9 @@ func Test_Same(t *testing.T) { "id": 100, "name": "john", } - err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.Assert(err2, nil) t.Assert(err3, nil) @@ -937,9 +937,9 @@ func Test_Different(t *testing.T) { "id": 100, "name": "john", } - err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Assoc(params1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val1).Assoc(params2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val1).Assoc(params3).Rules(rule).Run(ctx) t.Assert(err1, nil) t.AssertNE(err2, nil) t.AssertNE(err3, nil) @@ -953,10 +953,10 @@ func Test_In(t *testing.T) { val2 := "1" val3 := "100" val4 := "200" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -971,10 +971,10 @@ func Test_NotIn(t *testing.T) { val2 := "1" val3 := "100" val4 := "200" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) t.Assert(err1, nil) t.Assert(err2, nil) t.AssertNE(err3, nil) @@ -986,10 +986,10 @@ func Test_NotIn(t *testing.T) { val2 := "1" val3 := "100" val4 := "200" - err1 := g.Validator().Data(val1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(val2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(val3).Rules(rule).Messages(nil).Run(ctx) - err4 := g.Validator().Data(val4).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(val1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(val2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(val3).Rules(rule).Run(ctx) + err4 := g.Validator().Data(val4).Rules(rule).Run(ctx) t.Assert(err1, nil) t.Assert(err2, nil) t.AssertNE(err3, nil) @@ -999,10 +999,10 @@ func Test_NotIn(t *testing.T) { func Test_Regex1(t *testing.T) { rule := `regex:\d{6}|\D{6}|length:6,16` - if m := g.Validator().Data("123456").Rules(rule).Messages(nil).Run(ctx); m != nil { + if m := g.Validator().Data("123456").Rules(rule).Run(ctx); m != nil { t.Error(m) } - if m := g.Validator().Data("abcde6").Rules(rule).Messages(nil).Run(ctx); m == nil { + if m := g.Validator().Data("abcde6").Rules(rule).Run(ctx); m == nil { t.Error("校验失败") } } @@ -1013,9 +1013,9 @@ func Test_Regex2(t *testing.T) { str1 := "" str2 := "data" str3 := "data:image/jpeg;base64,/9jrbattq22r" - err1 := g.Validator().Data(str1).Rules(rule).Messages(nil).Run(ctx) - err2 := g.Validator().Data(str2).Rules(rule).Messages(nil).Run(ctx) - err3 := g.Validator().Data(str3).Rules(rule).Messages(nil).Run(ctx) + err1 := g.Validator().Data(str1).Rules(rule).Run(ctx) + err2 := g.Validator().Data(str2).Rules(rule).Run(ctx) + err3 := g.Validator().Data(str3).Rules(rule).Run(ctx) t.AssertNE(err1, nil) t.AssertNE(err2, nil) t.Assert(err3, nil) @@ -1032,7 +1032,7 @@ func Test_InternalError_String(t *testing.T) { Name string `v:"hh"` } aa := a{Name: "2"} - err := g.Validator().Data(&aa).Rules(nil).Run(ctx) + err := g.Validator().Data(&aa).Run(ctx) t.Assert(err.String(), "InvalidRules: hh") t.Assert(err.Strings(), g.Slice{"InvalidRules: hh"})