diff --git a/.example/net/ghttp/client/upload/client.go b/.example/net/ghttp/client/upload/client.go
index 0199e3441..a26548029 100644
--- a/.example/net/ghttp/client/upload/client.go
+++ b/.example/net/ghttp/client/upload/client.go
@@ -2,12 +2,34 @@ package main
import (
"fmt"
+ "github.com/gogf/gf/frame/g"
+ "path/filepath"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/glog"
)
+func SendXmlFile(gameId int, areaName string, filePath string) error {
+ path := filepath.FromSlash(filePath)
+ fmt.Println(path)
+ data := g.Map{
+ "gameName": gameId,
+ "area": areaName,
+ "file": "@file:" + path,
+ "contentType": "json",
+ }
+ if r, err := ghttp.Post("http://127.0.0.1:8199/upload", data); err != nil {
+ panic(err)
+ } else {
+ defer r.Close()
+ fmt.Println("ok")
+ }
+ return nil
+}
+
func main() {
+ SendXmlFile(1, "xxx", "/Users/john/Workspace/Go/GOPATH/src/github.com/gogf/gf/.example/net/ghttp/server/session.go")
+ return
path := "/home/john/Workspace/Go/github.com/gogf/gf/version.go"
r, e := ghttp.Post("http://127.0.0.1:8199/upload", "upload-file=@file:"+path)
if e != nil {
diff --git a/.example/net/ghttp/client/upload/server.go b/.example/net/ghttp/client/upload/server.go
index 482e1a7d6..26751703c 100644
--- a/.example/net/ghttp/client/upload/server.go
+++ b/.example/net/ghttp/client/upload/server.go
@@ -8,7 +8,7 @@ import (
// Upload uploads files to /tmp .
func Upload(r *ghttp.Request) {
saveDirPath := "/tmp/"
- files := r.GetUploadFiles("upload-file")
+ files := r.GetUploadFiles("file")
if _, err := files.Save(saveDirPath); err != nil {
r.Response.WriteExit(err)
}
diff --git a/.example/net/ghttp/server/object/user.go b/.example/net/ghttp/server/object/user.go
index 8bb926d68..28d76456e 100644
--- a/.example/net/ghttp/server/object/user.go
+++ b/.example/net/ghttp/server/object/user.go
@@ -5,21 +5,18 @@ import (
"github.com/gogf/gf/net/ghttp"
)
-type User struct {
-}
+type User struct{}
-func (c *User) Index(r *ghttp.Request) {
- r.Response.Write("Index")
-}
-
-// 不符合规范,不会被注册
-func (c *User) Test(r *ghttp.Request, value interface{}) {
+func (c *User) Test(r *ghttp.Request) {
r.Response.Write("Test")
}
func main() {
s := g.Server()
- s.BindObject("/user", new(User))
+ u := new(User)
+ s.Group("/", func(group *ghttp.RouterGroup) {
+ group.GET("/db-{table}/{id}", u, "Test")
+ })
s.SetPort(8199)
s.Run()
}
diff --git a/.example/other/test.go b/.example/other/test.go
index f6e15be50..f590bf262 100644
--- a/.example/other/test.go
+++ b/.example/other/test.go
@@ -1,23 +1,20 @@
package main
import (
- "fmt"
- "github.com/gogf/gf/encoding/gjson"
+ "github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
- "github.com/gogf/gf/util/guid"
)
-func CreateSessionId(r *ghttp.Request) string {
- var (
- agent = r.UserAgent()
- address = r.RemoteAddr
- cookie = r.Header.Get("Cookie")
- )
- return guid.S([]byte(agent), []byte(address), []byte(cookie))
-}
func main() {
- body := "{\"id\": 413231383385427875}"
- if dat, err := gjson.DecodeToJson(body); err == nil {
- fmt.Println(dat.MustToJsonString())
- }
+ s := g.Server()
+ s.BindHandler("POST:/login", func(r *ghttp.Request) {
+ r.Response.Write("login handler")
+ })
+ s.Group("/", func(group *ghttp.RouterGroup) {
+ group.GET("/test", func(r *ghttp.Request) {
+ r.Response.Write("for authenticated handler testing")
+ })
+ })
+ s.SetPort(8199)
+ s.Run()
}
diff --git a/README.MD b/README.MD
index d43448b79..641d4ea19 100644
--- a/README.MD
+++ b/README.MD
@@ -32,13 +32,13 @@ golang version >= 1.11
```
# Packages
-1. **Primary**
+1. **Primary Package**
The `gf` repository maintains some basic and most commonly used packages, keeping it as lightweight and simple as possible.
-1. **Community**
+1. **Community Package**
- The community packages are contrinuted and maintained by community members, which are reposited in `gogf` organization. Some of the community packages are seperated from th `gf` repository, which are not of common usage or are with heavy dependecies.
+ The community packages are contributed and maintained by community members, which are stored in `gogf` organization. Some of the community packages are separated from the `gf` repository, which are not of common usage or are with heavy dependencies.
# Architecture
diff --git a/net/ghttp/ghttp_server_router.go b/net/ghttp/ghttp_server_router.go
index 00ff298f9..1c21d397a 100644
--- a/net/ghttp/ghttp_server_router.go
+++ b/net/ghttp/ghttp_server_router.go
@@ -230,12 +230,40 @@ func (s *Server) compareRouterPriority(newItem *handlerItem, oldItem *handlerIte
if newItem.router.Priority < oldItem.router.Priority {
return false
}
- // Route type: {xxx} > :xxx > *xxx.
- // Eg: /name/act > /{name}/:act
- var fuzzyCountFieldNew, fuzzyCountFieldOld int
- var fuzzyCountNameNew, fuzzyCountNameOld int
- var fuzzyCountAnyNew, fuzzyCountAnyOld int
- var fuzzyCountTotalNew, fuzzyCountTotalOld int
+
+ // Compare the length of their URI,
+ // but the fuzzy and named parts of the URI are not calculated to the result.
+
+ // Eg:
+ // /admin-goods-{page} > /admin-{page}
+ // /{hash}.{type} > /{hash}
+ var uriNew, uriOld string
+ uriNew, _ = gregex.ReplaceString(`\{[^/]+?\}`, "", newItem.router.Uri)
+ uriOld, _ = gregex.ReplaceString(`\{[^/]+?\}`, "", oldItem.router.Uri)
+ uriNew, _ = gregex.ReplaceString(`:[^/]+?`, "", uriNew)
+ uriOld, _ = gregex.ReplaceString(`:[^/]+?`, "", uriOld)
+ uriNew, _ = gregex.ReplaceString(`\*[^/]*`, "", uriNew) // Replace "/*" and "/*any".
+ uriOld, _ = gregex.ReplaceString(`\*[^/]*`, "", uriOld) // Replace "/*" and "/*any".
+ if len(uriNew) > len(uriOld) {
+ return true
+ }
+ if len(uriNew) < len(uriOld) {
+ return false
+ }
+
+ // Route type checks: {xxx} > :xxx > *xxx.
+ // Eg:
+ // /name/act > /{name}/:act
+ var (
+ fuzzyCountFieldNew int
+ fuzzyCountFieldOld int
+ fuzzyCountNameNew int
+ fuzzyCountNameOld int
+ fuzzyCountAnyNew int
+ fuzzyCountAnyOld int
+ fuzzyCountTotalNew int
+ fuzzyCountTotalOld int
+ )
for _, v := range newItem.router.Uri {
switch v {
case '{':
@@ -282,24 +310,6 @@ func (s *Server) compareRouterPriority(newItem *handlerItem, oldItem *handlerIte
return false
}
- // It then compares the length of their URI,
- // but the fuzzy and named parts of the URI are not calculated to the result.
-
- // Eg: /admin-goods-{page} > /admin-{page}
- var uriNew, uriOld string
- uriNew, _ = gregex.ReplaceString(`\{[^/]+\}`, "", newItem.router.Uri)
- uriNew, _ = gregex.ReplaceString(`:[^/]+`, "", uriNew)
- uriNew, _ = gregex.ReplaceString(`\*[^/]+`, "", uriNew)
- uriOld, _ = gregex.ReplaceString(`\{[^/]+\}`, "", oldItem.router.Uri)
- uriOld, _ = gregex.ReplaceString(`:[^/]+`, "", uriOld)
- uriOld, _ = gregex.ReplaceString(`\*[^/]+`, "", uriOld)
- if len(uriNew) > len(uriOld) {
- return true
- }
- if len(uriNew) < len(uriOld) {
- return false
- }
-
// It then compares the accuracy of their http method,
// the more accurate the more priority.
if newItem.router.Method != gDEFAULT_METHOD {
diff --git a/net/ghttp/ghttp_unit_param_struct_test.go b/net/ghttp/ghttp_unit_param_struct_test.go
index cfd358c06..1d507b825 100644
--- a/net/ghttp/ghttp_unit_param_struct_test.go
+++ b/net/ghttp/ghttp_unit_param_struct_test.go
@@ -18,6 +18,67 @@ import (
"github.com/gogf/gf/test/gtest"
)
+func Test_Params_Parse1(t *testing.T) {
+ type User struct {
+ Id int
+ Name string
+ Map map[string]interface{}
+ }
+ p, _ := ports.PopRand()
+ s := g.Server(p)
+ s.BindHandler("/parse", func(r *ghttp.Request) {
+ if m := r.GetMap(); len(m) > 0 {
+ var user *User
+ if err := r.Parse(&user); err != nil {
+ r.Response.WriteExit(err)
+ }
+ r.Response.WriteExit(user.Map["id"], user.Map["score"])
+ }
+ })
+ 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.NewClient()
+ client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
+ t.Assert(client.PostContent("/parse", `{"id":1,"name":"john","map":{"id":1,"score":100}}`), `1100`)
+ })
+}
+
+// It does not support this kind of converting yet.
+//func Test_Params_Parse2(t *testing.T) {
+// type User struct {
+// Id int
+// Name string
+// Scores [][]int
+// }
+// p, _ := ports.PopRand()
+// s := g.Server(p)
+// s.BindHandler("/parse", func(r *ghttp.Request) {
+// if m := r.GetMap(); len(m) > 0 {
+// var user *User
+// if err := r.Parse(&user); err != nil {
+// r.Response.WriteExit(err)
+// }
+// r.Response.WriteExit(user.Scores)
+// }
+// })
+// 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.NewClient()
+// client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
+// t.Assert(client.PostContent("/parse", `{"id":1,"name":"john","scores":[[1,2,3]]}`), `1100`)
+// })
+//}
+
func Test_Params_Struct(t *testing.T) {
type User struct {
Id int
diff --git a/net/ghttp/ghttp_unit_router_basic_test.go b/net/ghttp/ghttp_unit_router_basic_test.go
index f034d3359..2b43dd775 100644
--- a/net/ghttp/ghttp_unit_router_basic_test.go
+++ b/net/ghttp/ghttp_unit_router_basic_test.go
@@ -16,7 +16,7 @@ import (
"github.com/gogf/gf/test/gtest"
)
-func Test_Router_Basic(t *testing.T) {
+func Test_Router_Basic1(t *testing.T) {
p, _ := ports.PopRand()
s := g.Server(p)
s.BindHandler("/:name", func(r *ghttp.Request) {
@@ -50,6 +50,29 @@ func Test_Router_Basic(t *testing.T) {
})
}
+func Test_Router_Basic2(t *testing.T) {
+ p, _ := ports.PopRand()
+ s := g.Server(p)
+ s.BindHandler("/{hash}", func(r *ghttp.Request) {
+ r.Response.Write(r.Get("hash"))
+ })
+ s.BindHandler("/{hash}.{type}", func(r *ghttp.Request) {
+ r.Response.Write(r.Get("type"))
+ })
+ 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.NewClient()
+ client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
+ t.Assert(client.GetContent("/data"), "data")
+ t.Assert(client.GetContent("/data.json"), "json")
+ })
+}
+
// HTTP method register.
func Test_Router_Method(t *testing.T) {
p, _ := ports.PopRand()
diff --git a/util/gconv/gconv_z_unit_struct_test.go b/util/gconv/gconv_z_unit_struct_test.go
index a16dd2be3..cb3300eb1 100644
--- a/util/gconv/gconv_z_unit_struct_test.go
+++ b/util/gconv/gconv_z_unit_struct_test.go
@@ -38,7 +38,7 @@ func Test_Struct_Basic1(t *testing.T) {
"PASS2": "456",
}
if err := gconv.Struct(params1, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
}
t.Assert(user, &User{
Uid: 1,
@@ -60,7 +60,7 @@ func Test_Struct_Basic1(t *testing.T) {
"password2": "222",
}
if err := gconv.Struct(params2, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
}
t.Assert(user, &User{
Uid: 2,
@@ -92,7 +92,7 @@ func Test_Struct_Basic2(t *testing.T) {
"PASS2": "456",
}
if err := gconv.Struct(params, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
}
t.Assert(user, &User{
Uid: 1,
@@ -117,15 +117,14 @@ func Test_Struct_Basic3(t *testing.T) {
"Name": "john",
}
if err := gconv.Struct(params, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
}
t.Assert(user.Uid, 1)
t.Assert(*user.Name, "john")
})
}
-// slice类型属性的赋值
-func Test_Struct_Attr_Slice(t *testing.T) {
+func Test_Struct_Attr_Slice1(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Scores []int
@@ -133,7 +132,7 @@ func Test_Struct_Attr_Slice(t *testing.T) {
scores := []interface{}{99, 100, 60, 140}
user := new(User)
if err := gconv.Struct(g.Map{"Scores": scores}, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
} else {
t.Assert(user, &User{
Scores: []int{99, 100, 60, 140},
@@ -142,6 +141,24 @@ func Test_Struct_Attr_Slice(t *testing.T) {
})
}
+// It does not support this kind of converting yet.
+//func Test_Struct_Attr_Slice2(t *testing.T) {
+// gtest.C(t, func(t *gtest.T) {
+// type User struct {
+// Scores [][]int
+// }
+// scores := []interface{}{[]interface{}{99, 100, 60, 140}}
+// user := new(User)
+// if err := gconv.Struct(g.Map{"Scores": scores}, user); err != nil {
+// t.Error(err)
+// } else {
+// t.Assert(user, &User{
+// Scores: [][]int{{99, 100, 60, 140}},
+// })
+// }
+// })
+//}
+
// 属性为struct对象
func Test_Struct_Attr_Struct(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
@@ -163,7 +180,7 @@ func Test_Struct_Attr_Struct(t *testing.T) {
// 嵌套struct转换
if err := gconv.Struct(scores, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
} else {
t.Assert(user, &User{
Scores: Score{
@@ -196,7 +213,7 @@ func Test_Struct_Attr_Struct_Ptr(t *testing.T) {
// 嵌套struct转换
if err := gconv.Struct(scores, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
} else {
t.Assert(user.Scores, &Score{
Name: "john",
@@ -227,7 +244,7 @@ func Test_Struct_Attr_Struct_Slice1(t *testing.T) {
// 嵌套struct转换,属性为slice类型,数值为map类型
if err := gconv.Struct(scores, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
} else {
t.Assert(user.Scores, []Score{
{
@@ -266,7 +283,7 @@ func Test_Struct_Attr_Struct_Slice2(t *testing.T) {
// 嵌套struct转换,属性为slice类型,数值为slice map类型
if err := gconv.Struct(scores, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
} else {
t.Assert(user.Scores, []Score{
{
@@ -309,7 +326,7 @@ func Test_Struct_Attr_Struct_Slice_Ptr(t *testing.T) {
// 嵌套struct转换,属性为slice类型,数值为slice map类型
if err := gconv.Struct(scores, user); err != nil {
- gtest.Error(err)
+ t.Error(err)
} else {
t.Assert(len(user.Scores), 2)
t.Assert(user.Scores[0], &Score{