mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
add middleware feature for ghttp.Server; improve router group feature for ghttp.Server
This commit is contained in:
@ -29,7 +29,7 @@ type Request struct {
|
||||
Router *Router // 匹配到的路由对象
|
||||
EnterTime int64 // 请求进入时间(微秒)
|
||||
LeaveTime int64 // 请求完成时间(微秒)
|
||||
MiddleWare *MiddleWare // 中间件功能调用对象
|
||||
Middleware *Middleware // 中间件功能调用对象
|
||||
handlers []*handlerParsedItem // 请求执行服务函数列表(包含中间件、路由函数、钩子函数)
|
||||
handlerIndex int // 当前执行函数的索引号
|
||||
hasHookHandler bool // 是否注册有钩子函数(用于请求时提高钩子函数功能启用判断效率)
|
||||
@ -59,7 +59,7 @@ func newRequest(s *Server, r *http.Request, w http.ResponseWriter) *Request {
|
||||
request.Cookie = GetCookie(request)
|
||||
request.Session = GetSession(request)
|
||||
request.Response.request = request
|
||||
request.MiddleWare = &MiddleWare{
|
||||
request.Middleware = &Middleware{
|
||||
request: request,
|
||||
}
|
||||
return request
|
||||
|
||||
@ -9,12 +9,12 @@ package ghttp
|
||||
import "reflect"
|
||||
|
||||
// 中间件对象
|
||||
type MiddleWare struct {
|
||||
type Middleware struct {
|
||||
request *Request
|
||||
}
|
||||
|
||||
// 执行下一个请求流程处理函数
|
||||
func (m *MiddleWare) Next() {
|
||||
func (m *Middleware) Next() {
|
||||
item := (*handlerParsedItem)(nil)
|
||||
for {
|
||||
// 是否停止请求执行
|
||||
@ -65,11 +65,11 @@ func (m *MiddleWare) Next() {
|
||||
item.handler.shutFunc(m.request)
|
||||
})
|
||||
}
|
||||
case gHANDLER_TYPE_HANDLER:
|
||||
case gHANDLER_TYPE_MIDDLEWARE:
|
||||
niceCallFunc(func() {
|
||||
item.handler.itemFunc(m.request)
|
||||
})
|
||||
case gHANDLER_TYPE_MIDDLEWARE:
|
||||
case gHANDLER_TYPE_HANDLER:
|
||||
niceCallFunc(func() {
|
||||
item.handler.itemFunc(m.request)
|
||||
})
|
||||
|
||||
@ -222,6 +222,9 @@ func GetServer(name ...interface{}) *Server {
|
||||
// 作为守护协程异步执行(当同一进程中存在多个Web Server时,需要采用这种方式执行),
|
||||
// 需要结合Wait方式一起使用.
|
||||
func (s *Server) Start() error {
|
||||
// 预处理路由注册项
|
||||
s.handlePreBindItems()
|
||||
|
||||
// 服务进程初始化,只会初始化一次
|
||||
serverProcessInit()
|
||||
|
||||
@ -299,8 +302,9 @@ func (s *Server) GetRouteMap() string {
|
||||
tablewriter.ALIGN_CENTER,
|
||||
tablewriter.ALIGN_CENTER,
|
||||
tablewriter.ALIGN_CENTER,
|
||||
tablewriter.ALIGN_LEFT,
|
||||
tablewriter.ALIGN_CENTER,
|
||||
tablewriter.ALIGN_CENTER,
|
||||
tablewriter.ALIGN_LEFT,
|
||||
tablewriter.ALIGN_LEFT,
|
||||
tablewriter.ALIGN_LEFT,
|
||||
tablewriter.ALIGN_CENTER,
|
||||
@ -319,7 +323,7 @@ func (s *Server) GetRouteMap() string {
|
||||
priority: len(registeredItems) - index - 1,
|
||||
}
|
||||
if item.handler.itemType == gHANDLER_TYPE_MIDDLEWARE {
|
||||
item.middleware = "YES"
|
||||
item.middleware = "MIDDLEWARE"
|
||||
}
|
||||
if _, ok := m[item.domain]; !ok {
|
||||
// 注意排序函数的逻辑,从小到达排序
|
||||
|
||||
@ -106,3 +106,17 @@ func (d *Domain) BindStatusHandlerByMap(handlerMap map[int]HandlerFunc) {
|
||||
d.BindStatusHandler(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
// 注册中间件,绑定到指定的路由规则上,中间件参数支持多个。
|
||||
func (d *Domain) BindMiddleware(pattern string, handlers ...HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindMiddleware(pattern+"@"+domain, handlers...)
|
||||
}
|
||||
}
|
||||
|
||||
// 注册中间件,绑定到全局路由规则("/*")上,中间件参数支持多个。
|
||||
func (d *Domain) AddMiddleware(handlers ...HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindMiddleware(gDEFAULT_MIDDLEWARE_PATTERN+"@"+domain, handlers...)
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,7 +116,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
} else {
|
||||
if len(request.handlers) > 0 {
|
||||
// 动态服务
|
||||
request.MiddleWare.Next()
|
||||
request.Middleware.Next()
|
||||
} else {
|
||||
if isStaticDir {
|
||||
// 静态目录
|
||||
|
||||
@ -10,140 +10,263 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/os/glog"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
)
|
||||
|
||||
// 分组路由对象
|
||||
type RouterGroup struct {
|
||||
server *Server // Server
|
||||
domain *Domain // Domain
|
||||
prefix string // URI前缀
|
||||
parent *RouterGroup // 父级分组路由
|
||||
server *Server // Server
|
||||
domain *Domain // Domain
|
||||
prefix string // URI前缀
|
||||
}
|
||||
|
||||
// 分组路由批量绑定项
|
||||
type GroupItem = []interface{}
|
||||
|
||||
// 预绑定路由项结构
|
||||
type groupPreBindItem struct {
|
||||
group *RouterGroup
|
||||
bindType string
|
||||
pattern string
|
||||
object interface{}
|
||||
params []interface{}
|
||||
}
|
||||
|
||||
var (
|
||||
// 预处理路由项存储数组
|
||||
preBindItems = make([]groupPreBindItem, 0, 64)
|
||||
)
|
||||
|
||||
// 处理预绑定路由项
|
||||
func (s *Server) handlePreBindItems() {
|
||||
for _, item := range preBindItems {
|
||||
if item.group.server != nil && item.group.server != s {
|
||||
continue
|
||||
}
|
||||
if item.group.domain != nil && item.group.domain.s != s {
|
||||
continue
|
||||
}
|
||||
item.group.doBind(item.bindType, item.pattern, item.object, item.params...)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取分组路由对象
|
||||
func (s *Server) Group(prefix ...string) *RouterGroup {
|
||||
func (s *Server) Group(prefix string, groups ...*RouterGroup) *RouterGroup {
|
||||
if prefix == "/" {
|
||||
prefix = ""
|
||||
}
|
||||
group := &RouterGroup{
|
||||
server: s,
|
||||
prefix: prefix,
|
||||
}
|
||||
if len(prefix) > 0 {
|
||||
group.prefix = prefix[0]
|
||||
if len(groups) > 0 {
|
||||
for _, v := range groups {
|
||||
v.parent = group
|
||||
}
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
// 获取分组路由对象
|
||||
func (d *Domain) Group(prefix ...string) *RouterGroup {
|
||||
// 获取分组路由对象(绑定域名)
|
||||
func (d *Domain) Group(prefix string, groups ...*RouterGroup) *RouterGroup {
|
||||
if prefix == "/" {
|
||||
prefix = ""
|
||||
}
|
||||
group := &RouterGroup{
|
||||
domain: d,
|
||||
prefix: prefix,
|
||||
}
|
||||
if len(prefix) > 0 {
|
||||
group.prefix = prefix[0]
|
||||
if len(groups) > 0 {
|
||||
for _, v := range groups {
|
||||
v.parent = group
|
||||
}
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
// 层级递归创建分组路由注册项
|
||||
func (g *RouterGroup) Group(prefix string, groups ...*RouterGroup) *RouterGroup {
|
||||
if prefix == "/" {
|
||||
prefix = ""
|
||||
}
|
||||
group := &RouterGroup{
|
||||
parent: g,
|
||||
server: g.server,
|
||||
domain: g.domain,
|
||||
prefix: g.prefix + prefix,
|
||||
}
|
||||
if len(groups) > 0 {
|
||||
for _, v := range groups {
|
||||
v.parent = group
|
||||
}
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
func (g *RouterGroup) Clone() *RouterGroup {
|
||||
return &RouterGroup{
|
||||
parent: g.parent,
|
||||
server: g.server,
|
||||
domain: g.domain,
|
||||
prefix: g.prefix,
|
||||
}
|
||||
}
|
||||
|
||||
// 执行分组路由批量绑定
|
||||
func (g *RouterGroup) Bind(items []GroupItem) {
|
||||
func (g *RouterGroup) Bind(items []GroupItem) *RouterGroup {
|
||||
group := g.Clone()
|
||||
for _, item := range items {
|
||||
if len(item) < 3 {
|
||||
glog.Fatalf("invalid router item: %s", item)
|
||||
}
|
||||
if strings.EqualFold(gconv.String(item[0]), "REST") {
|
||||
g.bind("REST", gconv.String(item[0])+":"+gconv.String(item[1]), item[2])
|
||||
} else {
|
||||
method := gconv.String(item[0])
|
||||
if strings.EqualFold(method, "ALL") {
|
||||
method = ""
|
||||
bindType := gstr.ToUpper(gconv.String(item[0]))
|
||||
switch bindType {
|
||||
case "REST":
|
||||
group.preBind("REST", gconv.String(item[0])+":"+gconv.String(item[1]), item[2])
|
||||
case "MIDDLEWARE":
|
||||
group.preBind("MIDDLEWARE", gconv.String(item[0])+":"+gconv.String(item[1]), item[2])
|
||||
default:
|
||||
if strings.EqualFold(bindType, "ALL") {
|
||||
bindType = ""
|
||||
} else {
|
||||
method += ":"
|
||||
bindType += ":"
|
||||
}
|
||||
if len(item) > 3 {
|
||||
g.bind("HANDLER", method+gconv.String(item[1]), item[2], item[3])
|
||||
group.preBind("HANDLER", bindType+gconv.String(item[1]), item[2], item[3])
|
||||
} else {
|
||||
g.bind("HANDLER", method+gconv.String(item[1]), item[2])
|
||||
group.preBind("HANDLER", bindType+gconv.String(item[1]), item[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
// 绑定所有的HTTP Method请求方式
|
||||
func (g *RouterGroup) ALL(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", gDEFAULT_METHOD+":"+pattern, object, params...)
|
||||
func (g *RouterGroup) ALL(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", gDEFAULT_METHOD+":"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// 绑定常用方法: GET/PUT/POST/DELETE
|
||||
func (g *RouterGroup) COMMON(pattern string, object interface{}, params ...interface{}) {
|
||||
g.GET(pattern, object, params...)
|
||||
g.PUT(pattern, object, params...)
|
||||
g.POST(pattern, object, params...)
|
||||
g.DELETE(pattern, object, params...)
|
||||
func (g *RouterGroup) COMMON(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
group := g.Clone()
|
||||
group.preBind("HANDLER", "GET:"+pattern, object, params...)
|
||||
group.preBind("HANDLER", "PUT:"+pattern, object, params...)
|
||||
group.preBind("HANDLER", "POST:"+pattern, object, params...)
|
||||
group.preBind("HANDLER", "DELETE:"+pattern, object, params...)
|
||||
return group
|
||||
}
|
||||
|
||||
func (g *RouterGroup) GET(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", "GET:"+pattern, object, params...)
|
||||
func (g *RouterGroup) GET(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "GET:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) PUT(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", "PUT:"+pattern, object, params...)
|
||||
func (g *RouterGroup) PUT(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "PUT:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) POST(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", "POST:"+pattern, object, params...)
|
||||
func (g *RouterGroup) POST(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "POST:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) DELETE(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", "DELETE:"+pattern, object, params...)
|
||||
func (g *RouterGroup) DELETE(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "DELETE:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) PATCH(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", "PATCH:"+pattern, object, params...)
|
||||
func (g *RouterGroup) PATCH(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "PATCH:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) HEAD(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", "HEAD:"+pattern, object, params...)
|
||||
func (g *RouterGroup) HEAD(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "HEAD:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) CONNECT(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", "CONNECT:"+pattern, object, params...)
|
||||
func (g *RouterGroup) CONNECT(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "CONNECT:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) OPTIONS(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", "OPTIONS:"+pattern, object, params...)
|
||||
func (g *RouterGroup) OPTIONS(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "OPTIONS:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) TRACE(pattern string, object interface{}, params ...interface{}) {
|
||||
g.bind("HANDLER", "TRACE:"+pattern, object, params...)
|
||||
func (g *RouterGroup) TRACE(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "TRACE:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// REST路由注册
|
||||
func (g *RouterGroup) REST(pattern string, object interface{}) {
|
||||
g.bind("REST", pattern, object)
|
||||
func (g *RouterGroup) REST(pattern string, object interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("REST", pattern, object)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) Hook(pattern string, hook string, handler HandlerFunc) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", pattern, handler, hook)
|
||||
}
|
||||
|
||||
func (g *RouterGroup) Middleware(handlers ...HandlerFunc) *RouterGroup {
|
||||
group := g.Clone()
|
||||
for _, handler := range handlers {
|
||||
group.preBind("MIDDLEWARE", "/*", handler)
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
func (g *RouterGroup) preBind(bindType string, pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
preBindItems = append(preBindItems, groupPreBindItem{
|
||||
group: g,
|
||||
bindType: bindType,
|
||||
pattern: pattern,
|
||||
object: object,
|
||||
params: params,
|
||||
})
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *RouterGroup) getPrefix() string {
|
||||
prefix := g.prefix
|
||||
parent := g.parent
|
||||
for parent != nil {
|
||||
prefix = parent.prefix + prefix
|
||||
parent = parent.parent
|
||||
}
|
||||
return prefix
|
||||
}
|
||||
|
||||
// 执行路由绑定
|
||||
func (g *RouterGroup) bind(bindType string, pattern string, object interface{}, params ...interface{}) {
|
||||
func (g *RouterGroup) doBind(bindType string, pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
prefix := g.getPrefix()
|
||||
// 注册路由处理
|
||||
if len(g.prefix) > 0 {
|
||||
if len(prefix) > 0 {
|
||||
domain, method, path, err := g.server.parsePattern(pattern)
|
||||
if err != nil {
|
||||
glog.Fatalf("invalid pattern: %s", pattern)
|
||||
}
|
||||
if bindType == "REST" {
|
||||
pattern = g.prefix + "/" + strings.TrimLeft(path, "/")
|
||||
pattern = prefix + "/" + strings.TrimLeft(path, "/")
|
||||
} else {
|
||||
pattern = g.server.serveHandlerKey(method, g.prefix+"/"+strings.TrimLeft(path, "/"), domain)
|
||||
pattern = g.server.serveHandlerKey(method, prefix+"/"+strings.TrimLeft(path, "/"), domain)
|
||||
}
|
||||
}
|
||||
methods := gconv.Strings(params)
|
||||
// 去掉可能重复出现的'//'符号
|
||||
pattern = gstr.Replace(pattern, "//", "/")
|
||||
// 将附加参数转换为字符串
|
||||
extras := gconv.Strings(params)
|
||||
// 判断是否事件回调注册
|
||||
if _, ok := object.(HandlerFunc); ok && len(methods) > 0 {
|
||||
if _, ok := object.(HandlerFunc); ok && len(extras) > 0 {
|
||||
bindType = "HOOK"
|
||||
}
|
||||
switch bindType {
|
||||
case "MIDDLEWARE":
|
||||
if h, ok := object.(HandlerFunc); ok {
|
||||
if g.server != nil {
|
||||
g.server.BindMiddleware(pattern, h)
|
||||
} else {
|
||||
g.domain.BindMiddleware(pattern, h)
|
||||
}
|
||||
} else {
|
||||
glog.Fatalf("invalid middleware handler for pattern:%s", pattern)
|
||||
}
|
||||
case "HANDLER":
|
||||
if h, ok := object.(HandlerFunc); ok {
|
||||
if g.server != nil {
|
||||
@ -152,11 +275,11 @@ func (g *RouterGroup) bind(bindType string, pattern string, object interface{},
|
||||
g.domain.BindHandler(pattern, h)
|
||||
}
|
||||
} else if g.isController(object) {
|
||||
if len(methods) > 0 {
|
||||
if len(extras) > 0 {
|
||||
if g.server != nil {
|
||||
g.server.BindControllerMethod(pattern, object.(Controller), methods[0])
|
||||
g.server.BindControllerMethod(pattern, object.(Controller), extras[0])
|
||||
} else {
|
||||
g.domain.BindControllerMethod(pattern, object.(Controller), methods[0])
|
||||
g.domain.BindControllerMethod(pattern, object.(Controller), extras[0])
|
||||
}
|
||||
} else {
|
||||
if g.server != nil {
|
||||
@ -166,11 +289,11 @@ func (g *RouterGroup) bind(bindType string, pattern string, object interface{},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(methods) > 0 {
|
||||
if len(extras) > 0 {
|
||||
if g.server != nil {
|
||||
g.server.BindObjectMethod(pattern, object, methods[0])
|
||||
g.server.BindObjectMethod(pattern, object, extras[0])
|
||||
} else {
|
||||
g.domain.BindObjectMethod(pattern, object, methods[0])
|
||||
g.domain.BindObjectMethod(pattern, object, extras[0])
|
||||
}
|
||||
} else {
|
||||
if g.server != nil {
|
||||
@ -197,14 +320,15 @@ func (g *RouterGroup) bind(bindType string, pattern string, object interface{},
|
||||
case "HOOK":
|
||||
if h, ok := object.(HandlerFunc); ok {
|
||||
if g.server != nil {
|
||||
g.server.BindHookHandler(pattern, methods[0], h)
|
||||
g.server.BindHookHandler(pattern, extras[0], h)
|
||||
} else {
|
||||
g.domain.BindHookHandler(pattern, methods[0], h)
|
||||
g.domain.BindHookHandler(pattern, extras[0], h)
|
||||
}
|
||||
} else {
|
||||
glog.Fatalf("invalid hook handler for pattern:%s", pattern)
|
||||
}
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
// 判断给定对象是否控制器对象:
|
||||
|
||||
@ -11,8 +11,12 @@ import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
gDEFAULT_MIDDLEWARE_PATTERN = "/*"
|
||||
)
|
||||
|
||||
// 注册中间件,绑定到指定的路由规则上,中间件参数支持多个。
|
||||
func (s *Server) BindMiddleWare(pattern string, handlers ...HandlerFunc) {
|
||||
func (s *Server) BindMiddleware(pattern string, handlers ...HandlerFunc) {
|
||||
for _, handler := range handlers {
|
||||
s.setHandler(pattern, &handlerItem{
|
||||
itemType: gHANDLER_TYPE_MIDDLEWARE,
|
||||
@ -23,9 +27,9 @@ func (s *Server) BindMiddleWare(pattern string, handlers ...HandlerFunc) {
|
||||
}
|
||||
|
||||
// 注册中间件,绑定到全局路由规则("/*")上,中间件参数支持多个。
|
||||
func (s *Server) AddMiddleWare(handlers ...HandlerFunc) {
|
||||
func (s *Server) AddMiddleware(handlers ...HandlerFunc) {
|
||||
for _, handler := range handlers {
|
||||
s.setHandler("/*", &handlerItem{
|
||||
s.setHandler(gDEFAULT_MIDDLEWARE_PATTERN, &handlerItem{
|
||||
itemType: gHANDLER_TYPE_MIDDLEWARE,
|
||||
itemName: runtime.FuncForPC(reflect.ValueOf(handler).Pointer()).Name(),
|
||||
itemFunc: handler,
|
||||
|
||||
@ -55,7 +55,7 @@ func (s *Server) searchHandlers(method, path, domain string) (parsedItems []*han
|
||||
array = strings.Split(path[1:], "/")
|
||||
}
|
||||
parsedItemList := glist.New()
|
||||
lastMiddleWareItem := (*glist.Element)(nil)
|
||||
lastMiddlewareItem := (*glist.Element)(nil)
|
||||
isServeHandlerAdded := false
|
||||
for _, domain := range domains {
|
||||
p, ok := s.serveTree[domain]
|
||||
@ -131,10 +131,10 @@ func (s *Server) searchHandlers(method, path, domain string) (parsedItems []*han
|
||||
|
||||
// 中间件需要排序
|
||||
case gHANDLER_TYPE_MIDDLEWARE:
|
||||
if lastMiddleWareItem == nil {
|
||||
lastMiddleWareItem = parsedItemList.PushFront(parsedItem)
|
||||
if lastMiddlewareItem == nil {
|
||||
lastMiddlewareItem = parsedItemList.PushFront(parsedItem)
|
||||
} else {
|
||||
lastMiddleWareItem = parsedItemList.InsertAfter(parsedItem, lastMiddleWareItem)
|
||||
lastMiddlewareItem = parsedItemList.InsertAfter(parsedItem, lastMiddlewareItem)
|
||||
}
|
||||
|
||||
// 钩子函数存在性判断
|
||||
|
||||
@ -16,28 +16,28 @@ import (
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_BindMiddleWare_Basic1(t *testing.T) {
|
||||
func Test_BindMiddleware_Basic1(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
})
|
||||
s.BindMiddleWare("/test", func(r *ghttp.Request) {
|
||||
s.BindMiddleware("/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("2")
|
||||
}, func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("4")
|
||||
})
|
||||
s.BindMiddleWare("/test/:name", func(r *ghttp.Request) {
|
||||
s.BindMiddleware("/test/:name", func(r *ghttp.Request) {
|
||||
r.Response.Write("5")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("6")
|
||||
}, func(r *ghttp.Request) {
|
||||
r.Response.Write("7")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("8")
|
||||
})
|
||||
s.SetPort(p)
|
||||
@ -57,28 +57,28 @@ func Test_BindMiddleWare_Basic1(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_BindMiddleWare_Basic2(t *testing.T) {
|
||||
func Test_BindMiddleware_Basic2(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
})
|
||||
s.BindMiddleWare("PUT:/test", func(r *ghttp.Request) {
|
||||
s.BindMiddleware("PUT:/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("2")
|
||||
}, func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("4")
|
||||
})
|
||||
s.BindMiddleWare("POST:/test/:name", func(r *ghttp.Request) {
|
||||
s.BindMiddleware("POST:/test/:name", func(r *ghttp.Request) {
|
||||
r.Response.Write("5")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("6")
|
||||
}, func(r *ghttp.Request) {
|
||||
r.Response.Write("7")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("8")
|
||||
})
|
||||
s.SetPort(p)
|
||||
@ -102,20 +102,20 @@ func Test_BindMiddleWare_Basic2(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_AddMiddleWare_Basic1(t *testing.T) {
|
||||
func Test_AddMiddleware_Basic1(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("2")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("4")
|
||||
})
|
||||
s.SetPort(p)
|
||||
@ -134,20 +134,20 @@ func Test_AddMiddleWare_Basic1(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_AddMiddleWare_Basic2(t *testing.T) {
|
||||
func Test_AddMiddleware_Basic2(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("PUT:/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("2")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("4")
|
||||
})
|
||||
s.SetPort(p)
|
||||
@ -168,18 +168,18 @@ func Test_AddMiddleWare_Basic2(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_AddMiddleWare_Basic3(t *testing.T) {
|
||||
func Test_AddMiddleware_Basic3(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
r.MiddleWare.Next()
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("2")
|
||||
})
|
||||
s.SetPort(p)
|
||||
@ -198,19 +198,19 @@ func Test_AddMiddleWare_Basic3(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_AddMiddleWare_Basic4(t *testing.T) {
|
||||
func Test_AddMiddleware_Basic4(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
r.MiddleWare.Next()
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("1")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("2")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
@ -228,19 +228,19 @@ func Test_AddMiddleWare_Basic4(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_AddMiddleWare_Basic5(t *testing.T) {
|
||||
func Test_AddMiddleware_Basic5(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("2")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
@ -258,40 +258,40 @@ func Test_AddMiddleWare_Basic5(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
type ObjectMiddleWare struct{}
|
||||
type ObjectMiddleware struct{}
|
||||
|
||||
func (o *ObjectMiddleWare) Init(r *ghttp.Request) {
|
||||
func (o *ObjectMiddleware) Init(r *ghttp.Request) {
|
||||
r.Response.Write("100")
|
||||
}
|
||||
|
||||
func (o *ObjectMiddleWare) Shut(r *ghttp.Request) {
|
||||
func (o *ObjectMiddleware) Shut(r *ghttp.Request) {
|
||||
r.Response.Write("200")
|
||||
}
|
||||
|
||||
func (o *ObjectMiddleWare) Index(r *ghttp.Request) {
|
||||
func (o *ObjectMiddleware) Index(r *ghttp.Request) {
|
||||
r.Response.Write("Object Index")
|
||||
}
|
||||
|
||||
func (o *ObjectMiddleWare) Show(r *ghttp.Request) {
|
||||
func (o *ObjectMiddleware) Show(r *ghttp.Request) {
|
||||
r.Response.Write("Object Show")
|
||||
}
|
||||
|
||||
func (o *ObjectMiddleWare) Info(r *ghttp.Request) {
|
||||
func (o *ObjectMiddleware) Info(r *ghttp.Request) {
|
||||
r.Response.Write("Object Info")
|
||||
}
|
||||
|
||||
func Test_AddMiddleWare_Basic6(t *testing.T) {
|
||||
func Test_AddMiddleware_Basic6(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindObject("/", new(ObjectMiddleWare))
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.BindObject("/", new(ObjectMiddleware))
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("2")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("4")
|
||||
})
|
||||
s.SetPort(p)
|
||||
@ -314,7 +314,7 @@ func Test_AddMiddleWare_Basic6(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Hook_MiddleWare_Basic1(t *testing.T) {
|
||||
func Test_Hook_Middleware_Basic1(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
@ -332,14 +332,14 @@ func Test_Hook_MiddleWare_Basic1(t *testing.T) {
|
||||
s.BindHookHandler("/*", ghttp.HOOK_AFTER_SERVE, func(r *ghttp.Request) {
|
||||
r.Response.Write("d")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("2")
|
||||
})
|
||||
s.AddMiddleWare(func(r *ghttp.Request) {
|
||||
s.AddMiddleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
r.MiddleWare.Next()
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("4")
|
||||
})
|
||||
s.SetPort(p)
|
||||
|
||||
85
net/ghttp/ghttp_unit_router_group_group_test.go
Normal file
85
net/ghttp/ghttp_unit_router_group_group_test.go
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// 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_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Router_Group_Group(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
g := s.Group("/")
|
||||
g.Group("/api.v2",
|
||||
g.Middleware(func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
r.Middleware.Next()
|
||||
r.Response.Write("2")
|
||||
}),
|
||||
g.GET("/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
}),
|
||||
g.Group("/order",
|
||||
g.GET("/list", func(r *ghttp.Request) {
|
||||
r.Response.Write("list")
|
||||
}),
|
||||
g.PUT("/update", func(r *ghttp.Request) {
|
||||
r.Response.Write("update")
|
||||
}),
|
||||
),
|
||||
g.Group("/user",
|
||||
g.GET("/info", func(r *ghttp.Request) {
|
||||
r.Response.Write("info")
|
||||
}),
|
||||
g.POST("/edit", func(r *ghttp.Request) {
|
||||
r.Response.Write("edit")
|
||||
}),
|
||||
g.DELETE("/drop", func(r *ghttp.Request) {
|
||||
r.Response.Write("drop")
|
||||
}),
|
||||
),
|
||||
g.Group("/hook",
|
||||
g.Hook("/*", ghttp.HOOK_BEFORE_SERVE, func(r *ghttp.Request) {
|
||||
r.Response.Write("hook any")
|
||||
}),
|
||||
g.Hook("/:name", ghttp.HOOK_BEFORE_SERVE, func(r *ghttp.Request) {
|
||||
r.Response.Write("hook name")
|
||||
}),
|
||||
),
|
||||
)
|
||||
s.SetPort(p)
|
||||
//s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/api.v2"), "12")
|
||||
gtest.Assert(client.GetContent("/api.v2/test"), "1test2")
|
||||
gtest.Assert(client.GetContent("/api.v2/hook"), "hook any12")
|
||||
gtest.Assert(client.GetContent("/api.v2/hook/name"), "hook namehook any12")
|
||||
gtest.Assert(client.GetContent("/api.v2/hook/name/any"), "hook any12")
|
||||
gtest.Assert(client.GetContent("/api.v2/order/list"), "1list2")
|
||||
gtest.Assert(client.GetContent("/api.v2/order/update"), "12")
|
||||
gtest.Assert(client.PutContent("/api.v2/order/update"), "1update2")
|
||||
gtest.Assert(client.GetContent("/api.v2/user/drop"), "12")
|
||||
gtest.Assert(client.DeleteContent("/api.v2/user/drop"), "1drop2")
|
||||
gtest.Assert(client.GetContent("/api.v2/user/edit"), "12")
|
||||
gtest.Assert(client.PostContent("/api.v2/user/edit"), "1edit2")
|
||||
gtest.Assert(client.GetContent("/api.v2/user/info"), "1info2")
|
||||
})
|
||||
}
|
||||
@ -16,7 +16,7 @@ import (
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Router_Group_HOOK1(t *testing.T) {
|
||||
func Test_Router_Group_Hook1(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
g := s.Group("/api")
|
||||
@ -45,7 +45,7 @@ func Test_Router_Group_HOOK1(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Router_Group_HOOK2(t *testing.T) {
|
||||
func Test_Router_Group_Hook2(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
g := s.Group("/api")
|
||||
@ -75,7 +75,7 @@ func Test_Router_Group_HOOK2(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Router_Group_HOOK3(t *testing.T) {
|
||||
func Test_Router_Group_Hook3(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.Group("/api").Bind([]g.Slice{
|
||||
|
||||
@ -20,10 +20,10 @@ func Test_Router_Hook_Basic(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHookHandlerByMap("/*", map[string]ghttp.HandlerFunc{
|
||||
"BeforeServe": func(r *ghttp.Request) { r.Response.Write("1") },
|
||||
"AfterServe": func(r *ghttp.Request) { r.Response.Write("2") },
|
||||
"BeforeOutput": func(r *ghttp.Request) { r.Response.Write("3") },
|
||||
"AfterOutput": func(r *ghttp.Request) { r.Response.Write("4") },
|
||||
ghttp.HOOK_BEFORE_SERVE: func(r *ghttp.Request) { r.Response.Write("1") },
|
||||
ghttp.HOOK_AFTER_SERVE: func(r *ghttp.Request) { r.Response.Write("2") },
|
||||
ghttp.HOOK_BEFORE_OUTPUT: func(r *ghttp.Request) { r.Response.Write("3") },
|
||||
ghttp.HOOK_AFTER_OUTPUT: func(r *ghttp.Request) { r.Response.Write("4") },
|
||||
})
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
@ -52,17 +52,17 @@ func Test_Router_Hook_Priority(t *testing.T) {
|
||||
})
|
||||
|
||||
s.BindHookHandlerByMap("/priority/:name", map[string]ghttp.HandlerFunc{
|
||||
"BeforeServe": func(r *ghttp.Request) {
|
||||
ghttp.HOOK_BEFORE_SERVE: func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/priority/*any", map[string]ghttp.HandlerFunc{
|
||||
"BeforeServe": func(r *ghttp.Request) {
|
||||
ghttp.HOOK_BEFORE_SERVE: func(r *ghttp.Request) {
|
||||
r.Response.Write("2")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/priority/show", map[string]ghttp.HandlerFunc{
|
||||
"BeforeServe": func(r *ghttp.Request) {
|
||||
ghttp.HOOK_BEFORE_SERVE: func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
},
|
||||
})
|
||||
@ -92,12 +92,12 @@ func Test_Router_Hook_Multi(t *testing.T) {
|
||||
})
|
||||
|
||||
s.BindHookHandlerByMap("/multi-hook", map[string]ghttp.HandlerFunc{
|
||||
"BeforeServe": func(r *ghttp.Request) {
|
||||
ghttp.HOOK_BEFORE_SERVE: func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/multi-hook", map[string]ghttp.HandlerFunc{
|
||||
"BeforeServe": func(r *ghttp.Request) {
|
||||
ghttp.HOOK_BEFORE_SERVE: func(r *ghttp.Request) {
|
||||
r.Response.Write("2")
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user