fix issue of grand.intn in x86 arch; add router group feature for WebServer

This commit is contained in:
John
2018-12-20 21:04:43 +08:00
parent d05b497cdb
commit d7381399aa
12 changed files with 332 additions and 162 deletions

View File

@ -24,7 +24,6 @@ install:
- cd $GITEE_GF
script:
# - cd g && go test -v ./...
- cd g && go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic
after_success:

View File

@ -9,18 +9,18 @@
package gins
import (
"fmt"
"gitee.com/johng/gf/g/container/gmap"
"gitee.com/johng/gf/g/database/gdb"
"gitee.com/johng/gf/g/database/gredis"
"gitee.com/johng/gf/g/os/gcfg"
"gitee.com/johng/gf/g/os/gcmd"
"gitee.com/johng/gf/g/os/genv"
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/os/gfsnotify"
"gitee.com/johng/gf/g/os/glog"
"gitee.com/johng/gf/g/os/gview"
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/container/gmap"
"gitee.com/johng/gf/g/util/gconv"
"gitee.com/johng/gf/g/database/gdb"
"gitee.com/johng/gf/g/os/gfsnotify"
"fmt"
"gitee.com/johng/gf/g/database/gredis"
"gitee.com/johng/gf/g/util/gregex"
)
@ -180,11 +180,11 @@ func Database(name...string) gdb.DB {
}
gdb.AddConfigGroup(group, cg)
}
// 使用gfsnotify进行文件监控当配置文件有任何变化时清空数据库配置缓存
gfsnotify.Add(config.GetFilePath(), func(event *gfsnotify.Event) {
instances.Remove(key)
})
}
// 使用gfsnotify进行文件监控当配置文件有任何变化时清空数据库配置缓存
gfsnotify.Add(config.GetFilePath(), func(event *gfsnotify.Event) {
instances.Remove(key)
})
if db, err := gdb.New(name...); err == nil {
return db
} else {

View File

@ -91,13 +91,13 @@ type (
}
// pattern与回调函数的绑定map
handlerMap map[string]*handlerItem
handlerMap = map[string]*handlerItem
// HTTP注册函数
HandlerFunc func(r *Request)
HandlerFunc = func(r *Request)
// 文件描述符map
listenerFdMap map[string]string
listenerFdMap = map[string]string
)
const (

View File

@ -20,24 +20,28 @@ import (
// 解析pattern
func (s *Server)parsePattern(pattern string) (domain, method, uri string, err error) {
uri = strings.TrimSpace(pattern)
func (s *Server)parsePattern(pattern string) (domain, method, path string, err error) {
path = strings.TrimSpace(pattern)
domain = gDEFAULT_DOMAIN
method = gDEFAULT_METHOD
if array, err := gregex.MatchString(`(.+):(.+)`, pattern); len(array) > 1 && err == nil {
method = strings.TrimSpace(array[1])
uri = strings.TrimSpace(array[2])
if array, err := gregex.MatchString(`([a-zA-Z]+):(.+)`, pattern); len(array) > 1 && err == nil {
path = strings.TrimSpace(array[2])
if v := strings.TrimSpace(array[1]); v != "" {
method = v
}
}
if array, err := gregex.MatchString(`(.+)@(.+)`, uri); len(array) > 1 && err == nil {
uri = strings.TrimSpace(array[1])
domain = strings.TrimSpace(array[2])
if array, err := gregex.MatchString(`(.+)@([\w\.\-]+)`, path); len(array) > 1 && err == nil {
path = strings.TrimSpace(array[1])
if v := strings.TrimSpace(array[2]); v != "" {
domain = v
}
}
if uri == "" {
if path == "" {
err = errors.New("invalid pattern")
}
// 去掉末尾的"/"符号,与路由匹配时处理一致
if uri != "/" {
uri = strings.TrimRight(uri, "/")
if path != "/" {
path = strings.TrimRight(path, "/")
}
return
}

View File

@ -7,12 +7,22 @@
package ghttp
import (
"gitee.com/johng/gf/g/os/glog"
"gitee.com/johng/gf/g/util/gconv"
"strings"
)
// 分组路由对象
type RouterGroup struct {
server *Server // Web Server
server *Server // Server
domain *Domain // Domain
prefix string // URI前缀
}
// 分组路由批量绑定项
type GroupItem = []interface{}
// 获取分组路由对象
func (s *Server) Group(prefix...string) *RouterGroup {
if len(prefix) > 0 {
@ -24,59 +34,160 @@ func (s *Server) Group(prefix...string) *RouterGroup {
return &RouterGroup{}
}
// REST路由注册
func (g *RouterGroup) REST(pattern string, object interface{}) {
// 获取分组路由对象
func (d *Domain) Group(prefix...string) *RouterGroup {
if len(prefix) > 0 {
return &RouterGroup{
domain : d,
prefix : prefix[0],
}
}
return &RouterGroup{}
}
// 执行分组路由批量绑定
func (g *RouterGroup) Bind(group string, items []GroupItem) {
for _, item := range items {
if len(item) < 3 {
glog.Fatalfln("invalid router item: %s", item)
}
if strings.EqualFold(gconv.String(item[0]), "REST") {
g.bind("REST", gconv.String(item[0]) + ":" + gconv.String(item[1]), item[2])
} else {
if len(item) > 3 {
g.bind("HANDLER", gconv.String(item[0]) + ":" + gconv.String(item[1]), item[2], item[3])
} else {
g.bind("HANDLER", gconv.String(item[0]) + ":" + gconv.String(item[1]), item[2])
}
}
}
}
// 绑定所有的HTTP Method请求方式
func (g *RouterGroup) ALL(pattern string, params...interface{}) {
func (g *RouterGroup) ALL(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", gDEFAULT_METHOD + ":" + pattern, object, params...)
}
func (g *RouterGroup) GET(pattern string, params...interface{}) {
func (g *RouterGroup) GET(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", "GET:" + pattern, object, params...)
}
func (g *RouterGroup) PUT(pattern string, params...interface{}) {
func (g *RouterGroup) PUT(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", "PUT:" + pattern, object, params...)
}
func (g *RouterGroup) POST(pattern string, params...interface{}) {
func (g *RouterGroup) POST(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", "POST:" + pattern, object, params...)
}
func (g *RouterGroup) DELETE(pattern string, params...interface{}) {
func (g *RouterGroup) DELETE(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", "DELETE:" + pattern, object, params...)
}
func (g *RouterGroup) PATCH(pattern string, params...interface{}) {
func (g *RouterGroup) PATCH(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", "PATCH:" + pattern, object, params...)
}
func (g *RouterGroup) HEAD(pattern string, params...interface{}) {
func (g *RouterGroup) HEAD(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", "HEAD:" + pattern, object, params...)
}
func (g *RouterGroup) CONNECT(pattern string, params...interface{}) {
func (g *RouterGroup) CONNECT(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", "CONNECT:" + pattern, object, params...)
}
func (g *RouterGroup) OPTIONS(pattern string, params...interface{}) {
func (g *RouterGroup) OPTIONS(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", "OPTIONS:" + pattern, object, params...)
}
func (g *RouterGroup) TRTACE(pattern string, params...interface{}) {
func (g *RouterGroup) TRACE(pattern string, object interface{}, params...interface{}) {
g.bind("HANDLER", "TRACE:" + pattern, object, params...)
}
// REST路由注册
func (g *RouterGroup) REST(pattern string, object interface{}) {
g.bind("REST", pattern, object)
}
// 执行路由绑定
func (g *RouterGroup) bind(method string, pattern string, params...interface{}) {
func (g *RouterGroup) bind(bindType string, pattern string, object interface{}, params...interface{}) {
// 注册路由处理
if len(g.prefix) > 0 {
domain, method, path, err := g.server.parsePattern(pattern)
if err != nil {
glog.Fatalfln("invalid pattern: %s", pattern)
}
if bindType == "HANDLER" {
pattern = g.server.serveHandlerKey(method, g.prefix + "/" + strings.TrimLeft(path, "/"), domain)
} else {
pattern = g.prefix + "/" + strings.TrimLeft(path, "/")
}
}
methods := gconv.Strings(params)
// 判断是否事件回调注册
if _, ok := object.(HandlerFunc); ok && len(methods) > 0 {
bindType = "HOOK"
}
switch bindType {
case "HANDLER":
if h, ok := object.(HandlerFunc); ok {
if g.server != nil {
g.server.BindHandler(pattern, h)
} else {
g.domain.BindHandler(pattern, h)
}
} else if c, ok := object.(Controller); ok {
if len(methods) > 0 {
if g.server != nil {
g.server.BindControllerMethod(pattern, c, methods[0])
} else {
g.domain.BindControllerMethod(pattern, c, methods[0])
}
} else {
if g.server != nil {
g.server.BindController(pattern, c)
} else {
g.domain.BindController(pattern, c)
}
}
} else {
if len(methods) > 0 {
if g.server != nil {
g.server.BindObjectMethod(pattern, object, methods[0])
} else {
g.domain.BindObjectMethod(pattern, object, methods[0])
}
} else {
if g.server != nil {
g.server.BindObject(pattern, object)
} else {
g.domain.BindObject(pattern, object)
}
}
}
case "REST":
if c, ok := object.(Controller); ok {
if g.server != nil {
g.server.BindControllerRest(pattern, c)
} else {
g.domain.BindControllerRest(pattern, c)
}
} else {
if g.server != nil {
g.server.BindObjectRest(pattern, object)
} else {
g.domain.BindObjectRest(pattern, object)
}
}
case "HOOK":
if h, ok := object.(HandlerFunc); ok {
if g.server != nil {
g.server.BindHookHandler(pattern, methods[0], h)
} else {
g.domain.BindHookHandler(pattern, methods[0], h)
}
} else {
glog.Fatalfln("invalid hook handler for pattern:%s", pattern)
}
}
}
// 判断给定对象是否控制器对象:
// 控制器必须包含以下公开的属性对象Request/Response/Server/Cookie/Session/View.
func (g *RouterGroup) isController(object interface{}) {
}

View File

@ -7,7 +7,6 @@
package gconv
import (
"fmt"
"reflect"
)
@ -77,12 +76,11 @@ func Ints(i interface{}) []int {
for _, v := range i.([]interface{}) {
array = append(array, Int(v))
}
default:
return []int{Int(i)}
}
if len(array) > 0 {
return array
}
return array
}
return []int{Int(i)}
}
// 任意类型转换为[]string类型
@ -95,71 +93,70 @@ func Strings(i interface{}) []string {
} else {
array := make([]string, 0)
switch i.(type) {
case []int:
for _, v := range i.([]int) {
array = append(array, String(v))
}
case []int8:
for _, v := range i.([]int8) {
array = append(array, String(v))
}
case []int16:
for _, v := range i.([]int16) {
array = append(array, String(v))
}
case []int32:
for _, v := range i.([]int32) {
array = append(array, String(v))
}
case []int64:
for _, v := range i.([]int64) {
array = append(array, String(v))
}
case []uint:
for _, v := range i.([]uint) {
array = append(array, String(v))
}
case []uint8:
for _, v := range i.([]uint8) {
array = append(array, String(v))
}
case []uint16:
for _, v := range i.([]uint16) {
array = append(array, String(v))
}
case []uint32:
for _, v := range i.([]uint32) {
array = append(array, String(v))
}
case []uint64:
for _, v := range i.([]uint64) {
array = append(array, String(v))
}
case []bool:
for _, v := range i.([]bool) {
array = append(array, String(v))
}
case []float32:
for _, v := range i.([]float32) {
array = append(array, String(v))
}
case []float64:
for _, v := range i.([]float64) {
array = append(array, String(v))
}
case []interface{}:
for _, v := range i.([]interface{}) {
array = append(array, String(v))
}
}
if len(array) > 0 {
return array
case []int:
for _, v := range i.([]int) {
array = append(array, String(v))
}
case []int8:
for _, v := range i.([]int8) {
array = append(array, String(v))
}
case []int16:
for _, v := range i.([]int16) {
array = append(array, String(v))
}
case []int32:
for _, v := range i.([]int32) {
array = append(array, String(v))
}
case []int64:
for _, v := range i.([]int64) {
array = append(array, String(v))
}
case []uint:
for _, v := range i.([]uint) {
array = append(array, String(v))
}
case []uint8:
for _, v := range i.([]uint8) {
array = append(array, String(v))
}
case []uint16:
for _, v := range i.([]uint16) {
array = append(array, String(v))
}
case []uint32:
for _, v := range i.([]uint32) {
array = append(array, String(v))
}
case []uint64:
for _, v := range i.([]uint64) {
array = append(array, String(v))
}
case []bool:
for _, v := range i.([]bool) {
array = append(array, String(v))
}
case []float32:
for _, v := range i.([]float32) {
array = append(array, String(v))
}
case []float64:
for _, v := range i.([]float64) {
array = append(array, String(v))
}
case []interface{}:
for _, v := range i.([]interface{}) {
array = append(array, String(v))
}
default:
return []string{String(i)}
}
return array
}
return []string{fmt.Sprintf("%v", i)}
}
// 任意类型转换为[]float64类型
// 类型转换为[]float64类型
func Floats(i interface{}) []float64 {
if i == nil {
return nil
@ -225,12 +222,11 @@ func Floats(i interface{}) []float64 {
for _, v := range i.([]interface{}) {
array = append(array, Float64(v))
}
default:
return []float64{Float64(i)}
}
if len(array) > 0 {
return array
}
return array
}
return []float64{Float64(i)}
}
// 任意类型转换为[]interface{}类型
@ -318,11 +314,10 @@ func Interfaces(i interface{}) []interface{} {
for i := 0; i < rv.NumField(); i++ {
array = append(array, rv.Field(i).Interface())
}
default:
return []interface{}{i}
}
}
if len(array) > 0 {
return array
}
return array
}
return []interface{}{i}
}

View File

@ -9,7 +9,6 @@ package grand
import (
"crypto/rand"
"encoding/binary"
"time"
)
const (
@ -34,8 +33,8 @@ func init() {
bufferChan <- binary.LittleEndian.Uint64(buffer[i : i + 8])
i ++
}
// 充分利用缓冲区数据,字节倒序生成,随机索引递增
step = int(time.Now().UnixNano())%n
// 充分利用缓冲区数据,随机索引递增
step = int(buffer[0])%10
for i := 0; i < n - 8; {
bufferChan <- binary.BigEndian.Uint64(buffer[i : i + 8])
i += step

View File

@ -1,6 +1,7 @@
package main
import (
"gitee.com/johng/gf/g"
"gitee.com/johng/gf/g/database/gdb"
"fmt"
"gitee.com/johng/gf/g/encoding/gparser"
@ -11,18 +12,14 @@ func main() {
Host : "127.0.0.1",
Port : "3306",
User : "root",
Pass : "123456",
Pass : "12345678",
Name : "test",
Type : "mysql",
Role : "master",
Charset : "utf8",
})
db, err := gdb.New()
if err != nil {
panic(err)
}
one, err := db.Table("user").Where("uid=?", 1).One()
db := g.DB()
one, err := db.Table("user").Where("id=?", 1).One()
if err != nil {
panic(err)
}
@ -33,7 +30,7 @@ func main() {
// 自定义方法方法转换为json/xml
jsonContent, _ := gparser.VarToJson(one.ToMap())
fmt.Println(jsonContent)
fmt.Println(string(jsonContent))
xmlContent, _ := gparser.VarToXml(one.ToMap())
fmt.Println(xmlContent)
fmt.Println(string(xmlContent))
}

View File

@ -0,0 +1,69 @@
package main
import (
"gitee.com/johng/gf/g"
"gitee.com/johng/gf/g/frame/gmvc"
"gitee.com/johng/gf/g/net/ghttp"
)
type Object struct {}
func (o *Object) Show(r *ghttp.Request) {
r.Response.Writeln("Object Show")
}
func (o *Object) Delete(r *ghttp.Request) {
r.Response.Writeln("Object REST Delete")
}
type Controller struct {
gmvc.Controller
}
func (c *Controller) Show() {
c.Response.Writeln("Controller Show")
}
func (c *Controller) Post() {
c.Response.Writeln("Controller REST Post")
}
func Handler(r *ghttp.Request) {
r.Response.Writeln("Handler")
}
func HookHandler(r *ghttp.Request) {
r.Response.Writeln("Hook Handler")
}
func main() {
s := g.Server()
obj := new(Object)
ctl := new(Controller)
// 分组路由方法注册
g := s.Group("/api")
g.ALL ("*", HookHandler, ghttp.HOOK_BEFORE_SERVE)
g.ALL ("/handler", Handler)
g.ALL ("/ctl", ctl)
g.GET ("/ctl/my-show", ctl, "Show")
g.REST("/ctl/rest", ctl)
g.ALL ("/obj", obj)
g.GET ("/obj/my-show", obj, "Show")
g.REST("/obj/rest", obj)
// 分组路由批量注册
s.Group("/api").Bind("/api", []ghttp.GroupItem{
{"ALL", "*", HookHandler, ghttp.HOOK_BEFORE_SERVE},
{"ALL", "/handler", Handler},
{"ALL", "/ctl", ctl},
{"GET", "/ctl/my-show", ctl, "Show"},
{"REST", "/ctl/rest", ctl},
{"ALL", "/obj", obj},
{"GET", "/obj/my-show", obj, "Show"},
{"REST", "/obj/rest", obj},
})
s.SetPort(8199)
s.Run()
}

View File

@ -7,7 +7,7 @@ type Registry struct {
Object interface{}
}
func BindGroup(group string, routers []Registry) {
func BindGroup(group string, routers [][]interface{}) {
}
@ -21,10 +21,10 @@ func HookFunc() {
func main() {
user := new(User)
BindGroup("/api", []Registry {
{"ALL", "/api/*", "BeforeServe", HookFunc},
{"ALL", "/order", "", new(Order)},
{"REST", "/product", "", new(Product)},
BindGroup("/api", [][]interface{} {
{"ALL", "/*", HookFunc, "BeforeServe"},
{"ALL", "/order", new(Order)},
{"REST", "/product", new(Product)},
{"GET", "/user/register", "Register", user},
{"GET", "/user/reset-pass", "ResetPassword", user},
{"POST", "/user/reset-pass", "ResetPassword", user},

View File

@ -2,24 +2,20 @@ package main
import (
"fmt"
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/os/gfsnotify"
"gitee.com/johng/gf/g"
"gitee.com/johng/gf/g/database/gdb"
"gitee.com/johng/gf/g/os/glog"
)
func main() {
path := "/Users/john/Temp"
_, err := gfsnotify.Add(path, func(event *gfsnotify.Event) {
fmt.Println(event)
if event.IsWrite() {
glog.Println("写入文件 : ", event.Path)
fmt.Printf("%s\n", gfile.GetContents(event.Path))
}
gdb.AddDefaultConfigNode(gdb.ConfigNode{
Type : "mysql",
Linkinfo : "root:12345678@tcp(127.0.0.1:3306)/test",
})
if err != nil {
glog.Fatal(err)
} else {
select {}
}
}
if r, err := g.Database().GetOne("select now() as time"); err != nil {
glog.Error("Mysql Init Select Now : %v", err)
} else {
fmt.Println(r.ToMap())
}
}

View File

@ -6,7 +6,7 @@ import (
)
func main() {
for i := 0; i < 10; i++ {
for i := 0; i < 100; i++ {
fmt.Println(grand.Rand(0, 99999))
}
}