github.com/zhongdalu/gf@v1.0.0/g/net/ghttp/ghttp_server_service_handler.go (about) 1 // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 // 服务注册. 7 8 package ghttp 9 10 import ( 11 "bytes" 12 "github.com/zhongdalu/gf/g/os/glog" 13 "github.com/zhongdalu/gf/g/text/gstr" 14 "reflect" 15 "runtime" 16 "strings" 17 ) 18 19 // 注意该方法是直接绑定函数的内存地址,执行的时候直接执行该方法,不会存在初始化新的控制器逻辑 20 func (s *Server) BindHandler(pattern string, handler HandlerFunc) { 21 s.bindHandlerItem(pattern, &handlerItem{ 22 name: runtime.FuncForPC(reflect.ValueOf(handler).Pointer()).Name(), 23 rtype: gROUTE_REGISTER_HANDLER, 24 ctype: nil, 25 fname: "", 26 faddr: handler, 27 }) 28 } 29 30 // 绑定URI到操作函数/方法 31 // pattern的格式形如:/user/list, put:/user, delete:/user, post:/user@johng.cn 32 // 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行 33 func (s *Server) bindHandlerItem(pattern string, item *handlerItem) { 34 if s.Status() == SERVER_STATUS_RUNNING { 35 glog.Error("server handlers cannot be changed while running") 36 return 37 } 38 s.setHandler(pattern, item) 39 } 40 41 // 通过映射数组绑定URI到操作函数/方法 42 func (s *Server) bindHandlerByMap(m handlerMap) { 43 for p, h := range m { 44 s.bindHandlerItem(p, h) 45 } 46 } 47 48 // 将内置的名称按照设定的规则合并到pattern中,内置名称按照{.xxx}规则命名。 49 // 规则1:pattern中的URI包含{.struct}关键字,则替换该关键字为结构体名称; 50 // 规则2:pattern中的URI包含{.method}关键字,则替换该关键字为方法名称; 51 // 规则2:如果不满足规则1,那么直接将防发明附加到pattern中的URI后面; 52 func (s *Server) mergeBuildInNameToPattern(pattern string, structName, methodName string, allowAppend bool) string { 53 structName = s.nameToUrlPart(structName) 54 methodName = s.nameToUrlPart(methodName) 55 pattern = strings.Replace(pattern, "{.struct}", structName, -1) 56 if strings.Index(pattern, "{.method}") != -1 { 57 return strings.Replace(pattern, "{.method}", methodName, -1) 58 } 59 // 不允许将方法名称append到路由末尾 60 if !allowAppend { 61 return pattern 62 } 63 // 检测域名后缀 64 array := strings.Split(pattern, "@") 65 // 分离URI(其实可能包含HTTP Method) 66 uri := array[0] 67 uri = strings.TrimRight(uri, "/") + "/" + methodName 68 // 加上指定域名后缀 69 if len(array) > 1 { 70 return uri + "@" + array[1] 71 } 72 return uri 73 } 74 75 // 将给定的名称转换为URL规范格式。 76 // 规则0: 全部转换为小写,方法名中间存在大写字母,转换为小写URI地址以“-”号链接每个单词; 77 // 规则1: 不处理名称,以原有名称构建成URI 78 // 规则2: 仅转为小写,单词间不使用连接符号 79 // 规则3: 采用驼峰命名方式 80 func (s *Server) nameToUrlPart(name string) string { 81 switch s.config.NameToUriType { 82 case NAME_TO_URI_TYPE_FULLNAME: 83 return name 84 85 case NAME_TO_URI_TYPE_ALLLOWER: 86 return strings.ToLower(name) 87 88 case NAME_TO_URI_TYPE_CAMEL: 89 part := bytes.NewBuffer(nil) 90 if gstr.IsLetterUpper(name[0]) { 91 part.WriteByte(name[0] + 32) 92 } else { 93 part.WriteByte(name[0]) 94 } 95 part.WriteString(name[1:]) 96 return part.String() 97 98 case NAME_TO_URI_TYPE_DEFAULT: 99 fallthrough 100 default: 101 part := bytes.NewBuffer(nil) 102 for i := 0; i < len(name); i++ { 103 if i > 0 && gstr.IsLetterUpper(name[i]) { 104 part.WriteByte('-') 105 } 106 if gstr.IsLetterUpper(name[i]) { 107 part.WriteByte(name[i] + 32) 108 } else { 109 part.WriteByte(name[i]) 110 } 111 } 112 return part.String() 113 } 114 }