comment update for package ghttp

This commit is contained in:
John
2020-05-09 19:19:42 +08:00
parent 80fddad64d
commit feff3ddce3
4 changed files with 92 additions and 63 deletions

View File

@ -16,9 +16,13 @@ import (
"github.com/gogf/gf/text/gstr"
)
// 绑定控制器,控制器需要实现 gmvc.Controller 接口,
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话,
// 第三个参数methods用以指定需要注册的方法支持多个方法名称多个方法以英文“,”号分隔,区分大小写.
// BindController registers controller to server routes with specified pattern. The controller
// needs to implement the gmvc.Controller interface. Each request of the controller bound in
// this way will initialize a new controller object for processing, corresponding to different
// request sessions.
//
// The optional parameter <method> is used to specify the method to be registered, which
// supports multiple method names, multiple methods are separated by char ',', case sensitive.
func (s *Server) BindController(pattern string, controller Controller, method ...string) {
bindMethod := ""
if len(method) > 0 {
@ -27,15 +31,23 @@ func (s *Server) BindController(pattern string, controller Controller, method ..
s.doBindController(pattern, controller, bindMethod, nil, "")
}
// 绑定路由到指定的方法执行, 第三个参数method仅支持一个方法注册不支持多个并且区分大小写。
// BindControllerMethod registers specified method to server routes with specified pattern.
//
// The optional parameter <method> is used to specify the method to be registered, which
// does not supports multiple method names but only one, case sensitive.
func (s *Server) BindControllerMethod(pattern string, controller Controller, method string) {
s.doBindControllerMethod(pattern, controller, method, nil, "")
}
// 绑定控制器(RESTFul)控制器需要实现gmvc.Controller接口
// 方法会识别HTTP方法并做REST绑定处理例如Post方法会绑定到HTTP POST的方法请求处理Delete方法会绑定到HTTP DELETE的方法请求处理
// 因此只会绑定HTTP Method对应的方法其他方法不会自动注册绑定
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
// BindControllerRest registers controller in REST API style to server with specified pattern.
// The controller needs to implement the gmvc.Controller interface. Each request of the controller
// bound in this way will initialize a new controller object for processing, corresponding to
// different request sessions.
// The method will recognize the HTTP method and do REST binding, for example:
// The method "Post" of controller will be bound to the HTTP POST method request processing,
// and the method "Delete" will be bound to the HTTP DELETE method request processing.
// Therefore, only the method corresponding to the HTTP Method will be bound, other methods will
// not automatically register the binding.
func (s *Server) BindControllerRest(pattern string, controller Controller) {
s.doBindControllerRest(pattern, controller, nil, "")
}
@ -52,7 +64,6 @@ func (s *Server) doBindController(
methodMap[strings.TrimSpace(v)] = true
}
}
// 当pattern中的method为all时去掉该method以便于后续方法判断
domain, method, path, err := s.parsePattern(pattern)
if err != nil {
s.Logger().Fatal(err)
@ -61,7 +72,7 @@ func (s *Server) doBindController(
if strings.EqualFold(method, gDEFAULT_METHOD) {
pattern = s.serveHandlerKey("", path, domain)
}
// 遍历控制器获取方法列表并构造成uri
// Retrieve a list of methods, create construct corresponding URI.
m := make(map[string]*handlerItem)
v := reflect.ValueOf(controller)
t := v.Type()
@ -82,13 +93,17 @@ func (s *Server) doBindController(
}
if _, ok := v.Method(i).Interface().(func()); !ok {
if len(methodMap) > 0 {
// 指定的方法名称注册,那么需要使用错误提示
s.Logger().Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`,
pkgPath, ctlName, methodName, v.Method(i).Type().String())
// If registering with specified method, print error.
s.Logger().Errorf(
`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`,
pkgPath, ctlName, methodName, v.Method(i).Type().String(),
)
} else {
// 否则只是Debug提示
s.Logger().Debugf(`ignore route method: %s.%s.%s defined as "%s", no match "func()" for controller registry`,
pkgPath, ctlName, methodName, v.Method(i).Type().String())
// Else, just print debug information.
s.Logger().Debugf(
`ignore route method: %s.%s.%s defined as "%s", no match "func()" for controller registry`,
pkgPath, ctlName, methodName, v.Method(i).Type().String(),
)
}
continue
}
@ -103,10 +118,13 @@ func (s *Server) doBindController(
middleware: middleware,
source: source,
}
// 如果方法中带有Index方法那么额外自动增加一个路由规则匹配主URI
// 例如: pattern为/user, 那么会同时注册/user及/user/index
// 这里处理新增/user路由绑定。
// 注意当pattern带有内置变量时不会自动加该路由。
// If there's "Index" method, then an additional route is automatically added
// to match the main URI, for example:
// If pattern is "/user", then "/user" and "/user/index" are both automatically
// registered.
//
// Note that if there's built-in variables in pattern, this route will not be added
// automatically.
if strings.EqualFold(methodName, "Index") && !gregex.IsMatchString(`\{\.\w+\}`, pattern) {
p := gstr.PosRI(key, "/index")
k := key[0:p] + key[p+6:]
@ -176,13 +194,11 @@ func (s *Server) doBindControllerRest(
pattern string, controller Controller,
middleware []HandlerFunc, source string,
) {
// 遍历控制器获取方法列表并构造成uri
m := make(map[string]*handlerItem)
v := reflect.ValueOf(controller)
t := v.Type()
pkgPath := t.Elem().PkgPath()
structName := t.Elem().Name()
// 如果存在与HttpMethod对应名字的方法那么绑定这些方法
for i := 0; i < v.NumMethod(); i++ {
methodName := t.Method(i).Name
if _, ok := methodsMap[strings.ToUpper(methodName)]; !ok {

View File

@ -14,14 +14,14 @@ import (
"github.com/gogf/gf/text/gstr"
)
// 注意该方法是直接绑定函数的内存地址,执行的时候直接执行该方法,不会存在初始化新的控制器逻辑
// BindHandler registers a handler function to server with given pattern.
func (s *Server) BindHandler(pattern string, handler HandlerFunc) {
s.doBindHandler(pattern, handler, nil, "")
}
// 绑定URI到操作函数/方法
// pattern的格式形如/user/list, put:/user, delete:/user, post:/user@johng.cn
// 支持RESTful的请求格式具体业务逻辑由绑定的处理方法来执行
// doBindHandler registers a handler function to server with given pattern.
// The parameter <pattern> is like:
// /user/list, put:/user, delete:/user, post:/user@goframe.org
func (s *Server) doBindHandler(
pattern string, handler HandlerFunc,
middleware []HandlerFunc, source string,
@ -35,17 +35,20 @@ func (s *Server) doBindHandler(
})
}
// 通过映射map绑定URI到操作函数/方法
// bindHandlerByMap registers handlers to server using map.
func (s *Server) bindHandlerByMap(m map[string]*handlerItem) {
for p, h := range m {
s.setHandler(p, h)
}
}
// 将内置的名称按照设定的规则合并到pattern中内置名称按照{.xxx}规则命名。
// 规则1pattern中的URI包含{.struct}关键字,则替换该关键字为结构体名称;
// 规则2pattern中的URI包含{.method}关键字,则替换该关键字为方法名称;
// 规则2如果不满足规则1那么直接将防发明附加到pattern中的URI后面
// mergeBuildInNameToPattern merges build-in names into the pattern according to the following
// rules, and the built-in names are named like "{.xxx}".
// Rule 1: The URI in pattern contains the {.struct} keyword, it then replaces the keyword with the struct name;
// Rule 2: The URI in pattern contains the {.method} keyword, it then replaces the keyword with the method name;
// Rule 2: If Rule 1 is not met, it then adds the method name directly to the URI in the pattern;
//
// The parameter <allowAppend> specifies whether allowing appending method name to the tail of pattern.
func (s *Server) mergeBuildInNameToPattern(pattern string, structName, methodName string, allowAppend bool) string {
structName = s.nameToUri(structName)
methodName = s.nameToUri(methodName)
@ -53,27 +56,25 @@ func (s *Server) mergeBuildInNameToPattern(pattern string, structName, methodNam
if strings.Index(pattern, "{.method}") != -1 {
return strings.Replace(pattern, "{.method}", methodName, -1)
}
// 不允许将方法名称append到路由末尾
if !allowAppend {
return pattern
}
// 检测域名后缀
// Check domain parameter.
array := strings.Split(pattern, "@")
// 分离URI(其实可能包含HTTP Method)
uri := array[0]
uri = strings.TrimRight(uri, "/") + "/" + methodName
// 加上指定域名后缀
// Append the domain parameter to URI.
if len(array) > 1 {
return uri + "@" + array[1]
}
return uri
}
// 将给定的名称转换为URL规范格式。
// 规则0: 全部转换为小写方法名中间存在大写字母转换为小写URI地址以“-”号链接每个单词;
// 规则1: 不处理名称以原有名称构建成URI
// 规则2: 仅转为小写,单词间不使用连接符号
// 规则3: 采用驼峰命名方式
// nameToUri converts the given name to URL format using following rules:
// Rule 0: Convert all method names to lowercase, add char '-' between words.
// Rule 1: Do not convert the method name, construct the URI with the original method name.
// Rule 2: Convert all method names to lowercase, no connecting symbols between words.
// Rule 3: Use camel case naming.
func (s *Server) nameToUri(name string) string {
switch s.config.NameToUriType {
case URI_TYPE_FULLNAME:

View File

@ -16,8 +16,12 @@ import (
"github.com/gogf/gf/text/gstr"
)
// 绑定对象到URI请求处理中会自动识别方法名称并附加到对应的URI地址后面
// 第三个参数methods用以指定需要注册的方法支持多个方法名称多个方法以英文“,”号分隔,区分大小写
// BindObject registers object to server routes with given pattern.
//
// The optional parameter <method> is used to specify the method to be registered, which
// supports multiple method names, multiple methods are separated by char ',', case sensitive.
//
// Note that the route method should be defined as ghttp.HandlerFunc.
func (s *Server) BindObject(pattern string, object interface{}, method ...string) {
bindMethod := ""
if len(method) > 0 {
@ -26,14 +30,18 @@ func (s *Server) BindObject(pattern string, object interface{}, method ...string
s.doBindObject(pattern, object, bindMethod, nil, "")
}
// 绑定对象到URI请求处理中会自动识别方法名称并附加到对应的URI地址后面
// 第三个参数method仅支持一个方法注册不支持多个并且区分大小写。
// BindObjectMethod registers specified method of object to server routes with given pattern.
//
// The optional parameter <method> is used to specify the method to be registered, which
// does not supports multiple method names but only one, case sensitive.
//
// Note that the route method should be defined as ghttp.HandlerFunc.
func (s *Server) BindObjectMethod(pattern string, object interface{}, method string) {
s.doBindObjectMethod(pattern, object, method, nil, "")
}
// 绑定对象到URI请求处理中会自动识别方法名称并附加到对应的URI地址后面,
// 需要注意对象方法的定义必须按照 ghttp.HandlerFunc 来定义
// BindObjectRest registers object in REST API style to server with specified pattern.
// Note that the route method should be defined as ghttp.HandlerFunc.
func (s *Server) BindObjectRest(pattern string, object interface{}) {
s.doBindObjectRest(pattern, object, nil, "")
}
@ -88,13 +96,11 @@ func (s *Server) doBindObject(
itemFunc, ok := v.Method(i).Interface().(func(*Request))
if !ok {
if len(methodMap) > 0 {
// 指定的方法名称注册,那么需要使用错误提示
s.Logger().Errorf(
`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`,
pkgPath, objName, methodName, v.Method(i).Type().String(),
)
} else {
// 否则只是Debug提示
s.Logger().Debugf(
`ignore route method: %s.%s.%s defined as "%s", no match "func(*ghttp.Request)" for object registry`,
pkgPath, objName, methodName, v.Method(i).Type().String(),
@ -112,8 +118,13 @@ func (s *Server) doBindObject(
middleware: middleware,
source: source,
}
// 如果方法中带有Index方法那么额外自动增加一个路由规则匹配主URI。
// 注意当pattern带有内置变量时不会自动加该路由。
// If there's "Index" method, then an additional route is automatically added
// to match the main URI, for example:
// If pattern is "/user", then "/user" and "/user/index" are both automatically
// registered.
//
// Note that if there's built-in variables in pattern, this route will not be added
// automatically.
if strings.EqualFold(methodName, "Index") && !gregex.IsMatchString(`\{\.\w+\}`, pattern) {
p := gstr.PosRI(key, "/index")
k := key[0:p] + key[p+6:]
@ -134,8 +145,6 @@ func (s *Server) doBindObject(
s.bindHandlerByMap(m)
}
// 绑定对象到URI请求处理中会自动识别方法名称并附加到对应的URI地址后面
// 第三个参数method仅支持一个方法注册不支持多个并且区分大小写。
func (s *Server) doBindObjectMethod(
pattern string, object interface{}, method string,
middleware []HandlerFunc, source string,
@ -166,8 +175,10 @@ func (s *Server) doBindObjectMethod(
}
itemFunc, ok := methodValue.Interface().(func(*Request))
if !ok {
s.Logger().Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`,
pkgPath, objName, methodName, methodValue.Type().String())
s.Logger().Errorf(
`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`,
pkgPath, objName, methodName, methodValue.Type().String(),
)
return
}
key := s.mergeBuildInNameToPattern(pattern, structName, methodName, false)
@ -213,8 +224,10 @@ func (s *Server) doBindObjectRest(
}
itemFunc, ok := v.Method(i).Interface().(func(*Request))
if !ok {
s.Logger().Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`,
pkgPath, objName, methodName, v.Method(i).Type().String())
s.Logger().Errorf(
`invalid route method: %s.%s.%s defined as "%s", but "func(*ghttp.Request)" is required for object registry`,
pkgPath, objName, methodName, v.Method(i).Type().String(),
)
continue
}
key := s.mergeBuildInNameToPattern(methodName+":"+pattern, structName, methodName, false)

View File

@ -3,7 +3,6 @@
// 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
@ -11,7 +10,7 @@ import (
"fmt"
)
// 查询状态码回调函数
// getStatusHandler retrieves and returns the handler for given status code.
func (s *Server) getStatusHandler(status int, r *Request) HandlerFunc {
domains := []string{r.GetHost(), gDEFAULT_DOMAIN}
for _, domain := range domains {
@ -22,23 +21,23 @@ func (s *Server) getStatusHandler(status int, r *Request) HandlerFunc {
return nil
}
// 不同状态码下的回调方法处理
// pattern格式domain#status
// setStatusHandler sets the handler for given status code.
// The parameter <pattern> is like: domain#status
func (s *Server) setStatusHandler(pattern string, handler HandlerFunc) {
s.statusHandlerMap[pattern] = handler
}
// 生成状态码回调函数map存储键名
// statusHandlerKey creates and returns key for given status and domain.
func (s *Server) statusHandlerKey(status int, domain string) string {
return fmt.Sprintf("%s#%d", domain, status)
}
// 绑定指定的状态码回调函数
// BindStatusHandler registers handler for given status code.
func (s *Server) BindStatusHandler(status int, handler HandlerFunc) {
s.setStatusHandler(s.statusHandlerKey(status, gDEFAULT_DOMAIN), handler)
}
// 通过map批量绑定状态码回调函数
// BindStatusHandlerByMap registers handler for given status code using map.
func (s *Server) BindStatusHandlerByMap(handlerMap map[int]HandlerFunc) {
for k, v := range handlerMap {
s.BindStatusHandler(k, v)