11package server
22
33import (
4+ "context"
45 "fmt"
56 "net"
67 "net/http"
78 "reflect"
9+ "regexp"
810 "runtime/debug"
911 "strings"
1012 "sync"
@@ -18,12 +20,24 @@ var (
1820 server = newHTTPServer ()
1921)
2022
23+ type uriRegexp struct {
24+ path string
25+ keys []string
26+ exp * regexp.Regexp
27+ source reflect.Type
28+ }
29+
2130// iface 对外服务接口, path格式:Method/URI
2231type iface struct {
2332 path string
2433 source reflect.Type
2534}
2635
36+ type prefix struct {
37+ path string
38+ uriExps []uriRegexp
39+ }
40+
2741type httpServer struct {
2842 path map [string ]iface
2943 prefix * btree.BTree
@@ -43,8 +57,8 @@ func newHTTPServer() *httpServer {
4357// Filter 请求过滤, 如果返回结果为nil,直接返回,不再进行后续处理.
4458type Filter func (http.ResponseWriter , * http.Request ) * http.Request
4559
46- func (i * iface ) Less (bi btree.Item ) bool {
47- return strings .Compare (i .path , bi .(* iface ).path ) == 1
60+ func (p * prefix ) Less (bi btree.Item ) bool {
61+ return strings .Compare (p .path , bi .(* prefix ).path ) == 1
4862}
4963
5064//NameToPath 类名转路径
@@ -74,9 +88,40 @@ func RegisterPrefix(obj interface{}, path string) error {
7488 return register (obj , path , true )
7589}
7690
77- //RegisterPath 注册url完全匹配.
78- func RegisterPath (obj interface {}, path string ) error {
79- return register (obj , path , true )
91+ var (
92+ keysExp * regexp.Regexp
93+ )
94+
95+ func init () {
96+ exp , err := regexp .Compile ("{(\\ w+)?}" )
97+ if err != nil {
98+ panic (err .Error ())
99+ }
100+ keysExp = exp
101+ }
102+
103+ func newURIRegexp (path string , source reflect.Type ) uriRegexp {
104+ ur := uriRegexp {
105+ path : path ,
106+ source : source ,
107+ }
108+
109+ //log.Debugf("path:%v", path)
110+ for _ , m := range keysExp .FindAllStringSubmatch (path , - 1 ) {
111+ //log.Debugf("path:%v, key:%#v", path, m)
112+ ur .keys = append (ur .keys , m [1 ])
113+ }
114+
115+ np := keysExp .ReplaceAllString (path , "(.+)" )
116+ exp , err := regexp .Compile (np )
117+ if err != nil {
118+ panic (err .Error ())
119+ }
120+ ur .exp = exp
121+
122+ // log.Debugf("uriRegexp:%#v", ur)
123+
124+ return ur
80125}
81126
82127func register (obj interface {}, path string , isPrefix bool ) error {
@@ -110,21 +155,37 @@ func register(obj interface{}, path string, isPrefix bool) error {
110155 continue
111156 }
112157
113- ifc := iface {
114- path : fmt .Sprintf ("%v%v" , method , path ),
115- source : rt .Elem (),
116- }
117-
118158 //前缀匹配
119159 if isPrefix {
120- if server .prefix .Has (& ifc ) {
121- panic (fmt .Sprintf ("exist url:%v %v" , method , path ))
160+ p := prefix {
161+ path : fmt .Sprintf ("%v%v" , method , path ),
162+ }
163+
164+ if idx := strings .Index (path , "{" ); idx > 0 {
165+ p .path = fmt .Sprintf ("%v%v" , method , path [:idx ])
166+ }
167+
168+ // log.Debugf("path:%v", p.path)
169+
170+ if server .prefix .Has (& p ) {
171+ p = * (server .prefix .Get (& p ).(* prefix ))
122172 }
123- server .prefix .ReplaceOrInsert (& ifc )
124- log .Infof ("add prefix %v %v %v" , method , path , rt )
173+
174+ exp := newURIRegexp (path , rt .Elem ())
175+
176+ p .uriExps = append (p .uriExps , exp )
177+
178+ server .prefix .ReplaceOrInsert (& p )
179+
180+ log .Infof ("add prefix %v %v %v %v" , method , exp .path , exp .keys , rt )
181+
125182 continue
126183 }
127184
185+ ifc := iface {
186+ path : fmt .Sprintf ("%v%v" , method , path ),
187+ source : rt .Elem (),
188+ }
128189 //全路径匹配
129190 if _ , ok := server .path [ifc .path ]; ok {
130191 panic (fmt .Sprintf ("exist url:%v %v" , method , path ))
@@ -144,27 +205,43 @@ func AddFilter(filter Filter) {
144205 server .filter = filter
145206}
146207
147- func getInterface (w http.ResponseWriter , r * http.Request ) (i iface , ok bool ) {
208+ func parseRequestValues (path string , ur uriRegexp ) context.Context {
209+ ctx := context .Background ()
210+ for i , v := range ur .exp .FindAllStringSubmatch (path , - 1 ) {
211+ //log.Debugf("i:%v, v:%#v, keys:%#v", i, v, ur.keys)
212+ ctx = context .WithValue (ctx , ur .keys [i ], v [1 ])
213+ }
214+ return ctx
215+ }
216+
217+ func getInterface (method , path string ) (reflect.Type , context.Context ) {
148218 server .RLock ()
149219 defer server .RUnlock ()
150220
151- path := r . Method + r . URL . Path
221+ path = method + path
152222
153- if i , ok = server .path [path ]; ok {
223+ if i , ok : = server .path [path ]; ok {
154224 //log.Debugf("find path:%v", path)
155- return
225+ return i . source , nil
156226 }
157227
228+ var p prefix
229+ var ok bool
158230 //如果完全匹配没找到,再找前缀的
159- server .prefix .AscendGreaterOrEqual (& iface {path : path }, func (item btree.Item ) bool {
160- i = * (item .(* iface ))
161- ok = strings .HasPrefix (path , i .path )
162- // log.Debugf("path:%v, ipath :%v, ok:%v", path, i .path, ok)
231+ server .prefix .AscendGreaterOrEqual (& prefix {path : path }, func (item btree.Item ) bool {
232+ p = * (item .(* prefix ))
233+ ok = strings .HasPrefix (path , p .path )
234+ //log.Debugf("path:%v, prefix :%v, ok:%v", path, p .path, ok)
163235 return ! ok
164236 })
165237
166- // log.Debugf("find prefix:%v, ok:%v", path, ok)
167- return
238+ for _ , ue := range p .uriExps {
239+ if ue .exp .MatchString (path ) {
240+ // log.Debugf("uri exp:%v, path:%v", ue, path)
241+ return ue .source , parseRequestValues (path , ue )
242+ }
243+ }
244+ return nil , nil
168245}
169246
170247//ServeHTTP 真正对外服务接口
@@ -183,16 +260,20 @@ func (s *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
183260 return
184261 }
185262
186- i , ok := getInterface (w , r )
187- if ! ok {
263+ tp , ctx := getInterface (r . Method , r . URL . Path )
264+ if tp == nil {
188265 log .Errorf ("%v %v %v not found." , r .RemoteAddr , r .Method , r .URL )
189266 SendResponse (w , http .StatusNotFound , "invalid request" )
190267 return
191268 }
192269
193- log .Debugf ("%v %v %v %v" , r .RemoteAddr , r .Method , r .URL , i .source )
270+ if ctx != nil {
271+ nr = nr .WithContext (ctx )
272+ }
273+
274+ log .Debugf ("%v %v %v %v" , r .RemoteAddr , r .Method , r .URL , tp )
194275
195- callback := reflect .New (i . source ).MethodByName (r .Method ).Interface ().(func (http.ResponseWriter , * http.Request ))
276+ callback := reflect .New (tp ).MethodByName (r .Method ).Interface ().(func (http.ResponseWriter , * http.Request ))
196277 callback (w , nr )
197278
198279 return
0 commit comments