github.com/zhongdalu/gf@v1.0.0/g/net/ghttp/ghttp_server_router_group.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  	"reflect"
    12  	"strings"
    13  
    14  	"github.com/zhongdalu/gf/g/os/glog"
    15  	"github.com/zhongdalu/gf/g/util/gconv"
    16  )
    17  
    18  // 分组路由对象
    19  type RouterGroup struct {
    20  	server *Server // Server
    21  	domain *Domain // Domain
    22  	prefix string  // URI前缀
    23  }
    24  
    25  // 分组路由批量绑定项
    26  type GroupItem = []interface{}
    27  
    28  // 获取分组路由对象
    29  func (s *Server) Group(prefix ...string) *RouterGroup {
    30  	group := &RouterGroup{
    31  		server: s,
    32  	}
    33  	if len(prefix) > 0 {
    34  		group.prefix = prefix[0]
    35  	}
    36  	return group
    37  }
    38  
    39  // 获取分组路由对象
    40  func (d *Domain) Group(prefix ...string) *RouterGroup {
    41  	if len(prefix) > 0 {
    42  		return &RouterGroup{
    43  			domain: d,
    44  			prefix: prefix[0],
    45  		}
    46  	}
    47  	return &RouterGroup{}
    48  }
    49  
    50  // 执行分组路由批量绑定
    51  func (g *RouterGroup) Bind(items []GroupItem) {
    52  	for _, item := range items {
    53  		if len(item) < 3 {
    54  			glog.Fatalf("invalid router item: %s", item)
    55  		}
    56  		if strings.EqualFold(gconv.String(item[0]), "REST") {
    57  			g.bind("REST", gconv.String(item[0])+":"+gconv.String(item[1]), item[2])
    58  		} else {
    59  			method := gconv.String(item[0])
    60  			if strings.EqualFold(method, "ALL") {
    61  				method = ""
    62  			} else {
    63  				method += ":"
    64  			}
    65  			if len(item) > 3 {
    66  				g.bind("HANDLER", method+gconv.String(item[1]), item[2], item[3])
    67  			} else {
    68  				g.bind("HANDLER", method+gconv.String(item[1]), item[2])
    69  			}
    70  		}
    71  	}
    72  }
    73  
    74  // 绑定所有的HTTP Method请求方式
    75  func (g *RouterGroup) ALL(pattern string, object interface{}, params ...interface{}) {
    76  	g.bind("HANDLER", gDEFAULT_METHOD+":"+pattern, object, params...)
    77  }
    78  
    79  // 绑定常用方法: GET/PUT/POST/DELETE
    80  func (g *RouterGroup) COMMON(pattern string, object interface{}, params ...interface{}) {
    81  	g.GET(pattern, object, params...)
    82  	g.PUT(pattern, object, params...)
    83  	g.POST(pattern, object, params...)
    84  	g.DELETE(pattern, object, params...)
    85  }
    86  
    87  func (g *RouterGroup) GET(pattern string, object interface{}, params ...interface{}) {
    88  	g.bind("HANDLER", "GET:"+pattern, object, params...)
    89  }
    90  
    91  func (g *RouterGroup) PUT(pattern string, object interface{}, params ...interface{}) {
    92  	g.bind("HANDLER", "PUT:"+pattern, object, params...)
    93  }
    94  
    95  func (g *RouterGroup) POST(pattern string, object interface{}, params ...interface{}) {
    96  	g.bind("HANDLER", "POST:"+pattern, object, params...)
    97  }
    98  
    99  func (g *RouterGroup) DELETE(pattern string, object interface{}, params ...interface{}) {
   100  	g.bind("HANDLER", "DELETE:"+pattern, object, params...)
   101  }
   102  
   103  func (g *RouterGroup) PATCH(pattern string, object interface{}, params ...interface{}) {
   104  	g.bind("HANDLER", "PATCH:"+pattern, object, params...)
   105  }
   106  
   107  func (g *RouterGroup) HEAD(pattern string, object interface{}, params ...interface{}) {
   108  	g.bind("HANDLER", "HEAD:"+pattern, object, params...)
   109  }
   110  
   111  func (g *RouterGroup) CONNECT(pattern string, object interface{}, params ...interface{}) {
   112  	g.bind("HANDLER", "CONNECT:"+pattern, object, params...)
   113  }
   114  
   115  func (g *RouterGroup) OPTIONS(pattern string, object interface{}, params ...interface{}) {
   116  	g.bind("HANDLER", "OPTIONS:"+pattern, object, params...)
   117  }
   118  
   119  func (g *RouterGroup) TRACE(pattern string, object interface{}, params ...interface{}) {
   120  	g.bind("HANDLER", "TRACE:"+pattern, object, params...)
   121  }
   122  
   123  // REST路由注册
   124  func (g *RouterGroup) REST(pattern string, object interface{}) {
   125  	g.bind("REST", pattern, object)
   126  }
   127  
   128  // 执行路由绑定
   129  func (g *RouterGroup) bind(bindType string, pattern string, object interface{}, params ...interface{}) {
   130  	// 注册路由处理
   131  	if len(g.prefix) > 0 {
   132  		domain, method, path, err := g.server.parsePattern(pattern)
   133  		if err != nil {
   134  			glog.Fatalf("invalid pattern: %s", pattern)
   135  		}
   136  		if bindType == "REST" {
   137  			pattern = g.prefix + "/" + strings.TrimLeft(path, "/")
   138  		} else {
   139  			pattern = g.server.serveHandlerKey(method, g.prefix+"/"+strings.TrimLeft(path, "/"), domain)
   140  		}
   141  	}
   142  	methods := gconv.Strings(params)
   143  	// 判断是否事件回调注册
   144  	if _, ok := object.(HandlerFunc); ok && len(methods) > 0 {
   145  		bindType = "HOOK"
   146  	}
   147  	switch bindType {
   148  	case "HANDLER":
   149  		if h, ok := object.(HandlerFunc); ok {
   150  			if g.server != nil {
   151  				g.server.BindHandler(pattern, h)
   152  			} else {
   153  				g.domain.BindHandler(pattern, h)
   154  			}
   155  		} else if g.isController(object) {
   156  			if len(methods) > 0 {
   157  				if g.server != nil {
   158  					g.server.BindControllerMethod(pattern, object.(Controller), methods[0])
   159  				} else {
   160  					g.domain.BindControllerMethod(pattern, object.(Controller), methods[0])
   161  				}
   162  			} else {
   163  				if g.server != nil {
   164  					g.server.BindController(pattern, object.(Controller))
   165  				} else {
   166  					g.domain.BindController(pattern, object.(Controller))
   167  				}
   168  			}
   169  		} else {
   170  			if len(methods) > 0 {
   171  				if g.server != nil {
   172  					g.server.BindObjectMethod(pattern, object, methods[0])
   173  				} else {
   174  					g.domain.BindObjectMethod(pattern, object, methods[0])
   175  				}
   176  			} else {
   177  				if g.server != nil {
   178  					g.server.BindObject(pattern, object)
   179  				} else {
   180  					g.domain.BindObject(pattern, object)
   181  				}
   182  			}
   183  		}
   184  	case "REST":
   185  		if g.isController(object) {
   186  			if g.server != nil {
   187  				g.server.BindControllerRest(pattern, object.(Controller))
   188  			} else {
   189  				g.domain.BindControllerRest(pattern, object.(Controller))
   190  			}
   191  		} else {
   192  			if g.server != nil {
   193  				g.server.BindObjectRest(pattern, object)
   194  			} else {
   195  				g.domain.BindObjectRest(pattern, object)
   196  			}
   197  		}
   198  	case "HOOK":
   199  		if h, ok := object.(HandlerFunc); ok {
   200  			if g.server != nil {
   201  				g.server.BindHookHandler(pattern, methods[0], h)
   202  			} else {
   203  				g.domain.BindHookHandler(pattern, methods[0], h)
   204  			}
   205  		} else {
   206  			glog.Fatalf("invalid hook handler for pattern:%s", pattern)
   207  		}
   208  	}
   209  }
   210  
   211  // 判断给定对象是否控制器对象:
   212  // 控制器必须包含以下公开的属性对象:Request/Response/Server/Cookie/Session/View.
   213  func (g *RouterGroup) isController(value interface{}) bool {
   214  	// 首先判断是否满足控制器接口定义
   215  	if _, ok := value.(Controller); !ok {
   216  		return false
   217  	}
   218  	// 其次检查控制器的必需属性
   219  	v := reflect.ValueOf(value)
   220  	if v.Kind() == reflect.Ptr {
   221  		v = v.Elem()
   222  	}
   223  	if v.FieldByName("Request").IsValid() && v.FieldByName("Response").IsValid() &&
   224  		v.FieldByName("Server").IsValid() && v.FieldByName("Cookie").IsValid() &&
   225  		v.FieldByName("Session").IsValid() && v.FieldByName("View").IsValid() {
   226  		return true
   227  	}
   228  	return false
   229  }