2019-02-02 16:18:25 +08:00
|
|
|
|
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
2018-07-31 21:05:02 +08:00
|
|
|
|
//
|
|
|
|
|
// 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,
|
2019-02-02 16:18:25 +08:00
|
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
2018-07-31 21:05:02 +08:00
|
|
|
|
// 服务注册.
|
|
|
|
|
|
|
|
|
|
package ghttp
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
2019-02-02 16:18:25 +08:00
|
|
|
|
"github.com/gogf/gf/g/os/glog"
|
2019-03-01 23:45:55 +08:00
|
|
|
|
"github.com/gogf/gf/g/text/gregex"
|
2018-07-31 21:05:02 +08:00
|
|
|
|
"strings"
|
|
|
|
|
"reflect"
|
2018-10-17 10:09:42 +08:00
|
|
|
|
"fmt"
|
2019-02-02 16:18:25 +08:00
|
|
|
|
"github.com/gogf/gf/g/text/gstr"
|
|
|
|
|
"github.com/gogf/gf/g/os/gfile"
|
2018-07-31 21:05:02 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
2018-08-16 21:33:47 +08:00
|
|
|
|
// 第三个参数methods用以指定需要注册的方法,支持多个方法名称,多个方法以英文“,”号分隔,区分大小写
|
2018-07-31 21:05:02 +08:00
|
|
|
|
func (s *Server)BindObject(pattern string, obj interface{}, methods...string) error {
|
2018-08-16 21:33:47 +08:00
|
|
|
|
methodMap := (map[string]bool)(nil)
|
2018-07-31 21:05:02 +08:00
|
|
|
|
if len(methods) > 0 {
|
2018-08-16 21:33:47 +08:00
|
|
|
|
methodMap = make(map[string]bool)
|
|
|
|
|
for _, v := range strings.Split(methods[0], ",") {
|
|
|
|
|
methodMap[strings.TrimSpace(v)] = true
|
|
|
|
|
}
|
2018-07-31 21:05:02 +08:00
|
|
|
|
}
|
2018-10-17 10:09:42 +08:00
|
|
|
|
m := make(handlerMap)
|
|
|
|
|
v := reflect.ValueOf(obj)
|
|
|
|
|
t := v.Type()
|
2018-07-31 21:05:02 +08:00
|
|
|
|
sname := t.Elem().Name()
|
2018-08-17 19:01:49 +08:00
|
|
|
|
finit := (func(*Request))(nil)
|
|
|
|
|
fshut := (func(*Request))(nil)
|
|
|
|
|
if v.MethodByName("Init").IsValid() {
|
|
|
|
|
finit = v.MethodByName("Init").Interface().(func(*Request))
|
|
|
|
|
}
|
|
|
|
|
if v.MethodByName("Shut").IsValid() {
|
|
|
|
|
fshut = v.MethodByName("Shut").Interface().(func(*Request))
|
|
|
|
|
}
|
2018-10-17 10:09:42 +08:00
|
|
|
|
pkgPath := t.Elem().PkgPath()
|
|
|
|
|
pkgName := gfile.Basename(pkgPath)
|
2018-07-31 21:05:02 +08:00
|
|
|
|
for i := 0; i < v.NumMethod(); i++ {
|
2018-08-16 21:33:47 +08:00
|
|
|
|
mname := t.Method(i).Name
|
|
|
|
|
if methodMap != nil && !methodMap[mname] {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2018-08-17 19:01:49 +08:00
|
|
|
|
if mname == "Init" || mname == "Shut" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2018-10-31 22:39:58 +08:00
|
|
|
|
faddr, ok := v.Method(i).Interface().(func(*Request))
|
|
|
|
|
if !ok {
|
|
|
|
|
if methodMap != nil {
|
|
|
|
|
s := fmt.Sprintf(`invalid medthod definition "%s", while "func(*Request))" is required`, v.Method(i).Type().String())
|
2018-11-01 08:37:23 +08:00
|
|
|
|
glog.Error(s)
|
2018-10-31 22:39:58 +08:00
|
|
|
|
return errors.New(s)
|
|
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
2018-10-17 10:09:42 +08:00
|
|
|
|
objName := gstr.Replace(t.String(), fmt.Sprintf(`%s.`, pkgName), "")
|
|
|
|
|
if objName[0] == '*' {
|
|
|
|
|
objName = fmt.Sprintf(`(%s)`, objName)
|
|
|
|
|
}
|
2018-08-16 21:33:47 +08:00
|
|
|
|
key := s.mergeBuildInNameToPattern(pattern, sname, mname, true)
|
2018-07-31 21:05:02 +08:00
|
|
|
|
m[key] = &handlerItem {
|
2018-10-17 10:09:42 +08:00
|
|
|
|
name : fmt.Sprintf(`%s.%s.%s`, pkgPath, objName, mname),
|
2018-08-19 11:25:15 +08:00
|
|
|
|
rtype : gROUTE_REGISTER_OBJECT,
|
2018-07-31 21:05:02 +08:00
|
|
|
|
ctype : nil,
|
|
|
|
|
fname : "",
|
2018-10-31 22:39:58 +08:00
|
|
|
|
faddr : faddr,
|
2018-08-17 19:01:49 +08:00
|
|
|
|
finit : finit,
|
|
|
|
|
fshut : fshut,
|
2018-07-31 21:05:02 +08:00
|
|
|
|
}
|
2019-03-01 23:45:55 +08:00
|
|
|
|
// 如果方法中带有Index方法,那么额外自动增加一个路由规则匹配主URI。
|
|
|
|
|
// 注意,当pattern带有内置变量时,不会自动加该路由。
|
|
|
|
|
if strings.EqualFold(mname, "Index") && !gregex.IsMatchString(`\{\.\w+\}`, pattern) {
|
2019-02-26 22:21:57 +08:00
|
|
|
|
p := gstr.PosR(key, "/index")
|
2019-02-28 14:07:00 +08:00
|
|
|
|
k := key[0 : p] + key[p + 6 : ]
|
|
|
|
|
if len(k) == 0 {
|
|
|
|
|
k = "/"
|
|
|
|
|
}
|
|
|
|
|
m[k] = &handlerItem {
|
2018-10-17 10:09:42 +08:00
|
|
|
|
name : fmt.Sprintf(`%s.%s.%s`, pkgPath, objName, mname),
|
2018-08-19 11:25:15 +08:00
|
|
|
|
rtype : gROUTE_REGISTER_OBJECT,
|
2018-07-31 21:05:02 +08:00
|
|
|
|
ctype : nil,
|
|
|
|
|
fname : "",
|
2018-10-31 22:39:58 +08:00
|
|
|
|
faddr : faddr,
|
2018-08-17 19:01:49 +08:00
|
|
|
|
finit : finit,
|
|
|
|
|
fshut : fshut,
|
2018-07-31 21:05:02 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return s.bindHandlerByMap(m)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
|
|
|
|
// 第三个参数methods支持多个方法注册,多个方法以英文“,”号分隔,区分大小写
|
2018-08-16 21:33:47 +08:00
|
|
|
|
func (s *Server)BindObjectMethod(pattern string, obj interface{}, method string) error {
|
2018-07-31 21:05:02 +08:00
|
|
|
|
m := make(handlerMap)
|
|
|
|
|
v := reflect.ValueOf(obj)
|
|
|
|
|
t := v.Type()
|
|
|
|
|
sname := t.Elem().Name()
|
2018-08-16 21:33:47 +08:00
|
|
|
|
mname := strings.TrimSpace(method)
|
|
|
|
|
fval := v.MethodByName(mname)
|
|
|
|
|
if !fval.IsValid() {
|
|
|
|
|
return errors.New("invalid method name:" + mname)
|
|
|
|
|
}
|
2018-10-31 22:39:58 +08:00
|
|
|
|
faddr, ok := fval.Interface().(func(*Request))
|
|
|
|
|
if !ok {
|
|
|
|
|
s := fmt.Sprintf(`invalid medthod definition "%s", while "func(*Request)" is required`, fval.Type().String())
|
2018-11-01 08:37:23 +08:00
|
|
|
|
glog.Error(s)
|
2018-10-31 22:39:58 +08:00
|
|
|
|
return errors.New(s)
|
|
|
|
|
}
|
2018-08-17 19:01:49 +08:00
|
|
|
|
finit := (func(*Request))(nil)
|
|
|
|
|
fshut := (func(*Request))(nil)
|
|
|
|
|
if v.MethodByName("Init").IsValid() {
|
|
|
|
|
finit = v.MethodByName("Init").Interface().(func(*Request))
|
|
|
|
|
}
|
|
|
|
|
if v.MethodByName("Shut").IsValid() {
|
|
|
|
|
fshut = v.MethodByName("Shut").Interface().(func(*Request))
|
|
|
|
|
}
|
2018-10-17 10:09:42 +08:00
|
|
|
|
pkgPath := t.Elem().PkgPath()
|
|
|
|
|
pkgName := gfile.Basename(pkgPath)
|
|
|
|
|
objName := gstr.Replace(t.String(), fmt.Sprintf(`%s.`, pkgName), "")
|
|
|
|
|
if objName[0] == '*' {
|
|
|
|
|
objName = fmt.Sprintf(`(%s)`, objName)
|
|
|
|
|
}
|
2018-08-16 21:33:47 +08:00
|
|
|
|
key := s.mergeBuildInNameToPattern(pattern, sname, mname, false)
|
|
|
|
|
m[key] = &handlerItem{
|
2018-10-17 10:09:42 +08:00
|
|
|
|
name : fmt.Sprintf(`%s.%s.%s`, pkgPath, objName, mname),
|
2018-08-19 11:25:15 +08:00
|
|
|
|
rtype : gROUTE_REGISTER_OBJECT,
|
2018-08-16 21:33:47 +08:00
|
|
|
|
ctype : nil,
|
|
|
|
|
fname : "",
|
2018-10-31 22:39:58 +08:00
|
|
|
|
faddr : faddr,
|
2018-08-17 19:01:49 +08:00
|
|
|
|
finit : finit,
|
|
|
|
|
fshut : fshut,
|
2018-07-31 21:05:02 +08:00
|
|
|
|
}
|
2018-08-16 21:33:47 +08:00
|
|
|
|
|
2018-07-31 21:05:02 +08:00
|
|
|
|
return s.bindHandlerByMap(m)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面
|
|
|
|
|
// 需要注意对象方法的定义必须按照ghttp.HandlerFunc来定义
|
|
|
|
|
func (s *Server)BindObjectRest(pattern string, obj interface{}) error {
|
2018-08-17 19:01:49 +08:00
|
|
|
|
m := make(handlerMap)
|
|
|
|
|
v := reflect.ValueOf(obj)
|
|
|
|
|
t := v.Type()
|
2019-03-01 23:45:55 +08:00
|
|
|
|
sname := t.Elem().Name()
|
2018-08-17 19:01:49 +08:00
|
|
|
|
finit := (func(*Request))(nil)
|
|
|
|
|
fshut := (func(*Request))(nil)
|
|
|
|
|
if v.MethodByName("Init").IsValid() {
|
|
|
|
|
finit = v.MethodByName("Init").Interface().(func(*Request))
|
|
|
|
|
}
|
|
|
|
|
if v.MethodByName("Shut").IsValid() {
|
|
|
|
|
fshut = v.MethodByName("Shut").Interface().(func(*Request))
|
|
|
|
|
}
|
2018-10-17 10:09:42 +08:00
|
|
|
|
pkgPath := t.Elem().PkgPath()
|
2018-07-31 21:05:02 +08:00
|
|
|
|
for i := 0; i < v.NumMethod(); i++ {
|
2018-10-17 10:09:42 +08:00
|
|
|
|
mname := t.Method(i).Name
|
|
|
|
|
method := strings.ToUpper(mname)
|
2019-03-01 23:45:55 +08:00
|
|
|
|
if _, ok := methodsMap[method]; !ok {
|
2018-07-31 21:05:02 +08:00
|
|
|
|
continue
|
|
|
|
|
}
|
2018-10-31 22:39:58 +08:00
|
|
|
|
faddr, ok := v.Method(i).Interface().(func(*Request))
|
|
|
|
|
if !ok {
|
|
|
|
|
s := fmt.Sprintf(`invalid medthod definition "%s", while "func()" is required`, v.Method(i).Type().String())
|
2018-11-01 08:37:23 +08:00
|
|
|
|
glog.Error(s)
|
2018-10-31 22:39:58 +08:00
|
|
|
|
return errors.New(s)
|
|
|
|
|
}
|
2018-10-17 10:09:42 +08:00
|
|
|
|
pkgName := gfile.Basename(pkgPath)
|
|
|
|
|
objName := gstr.Replace(t.String(), fmt.Sprintf(`%s.`, pkgName), "")
|
|
|
|
|
if objName[0] == '*' {
|
|
|
|
|
objName = fmt.Sprintf(`(%s)`, objName)
|
|
|
|
|
}
|
2019-03-01 23:45:55 +08:00
|
|
|
|
key := s.mergeBuildInNameToPattern(mname + ":" + pattern, sname, mname, false)
|
2018-07-31 21:05:02 +08:00
|
|
|
|
m[key] = &handlerItem {
|
2018-10-17 10:09:42 +08:00
|
|
|
|
name : fmt.Sprintf(`%s.%s.%s`, pkgPath, objName, mname),
|
2018-08-19 11:25:15 +08:00
|
|
|
|
rtype : gROUTE_REGISTER_OBJECT,
|
2018-07-31 21:05:02 +08:00
|
|
|
|
ctype : nil,
|
|
|
|
|
fname : "",
|
2018-10-31 22:39:58 +08:00
|
|
|
|
faddr : faddr,
|
2018-08-17 19:01:49 +08:00
|
|
|
|
finit : finit,
|
|
|
|
|
fshut : fshut,
|
2018-07-31 21:05:02 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return s.bindHandlerByMap(m)
|
|
|
|
|
}
|