add middleware feature for ghttp.Server; improve router group feature for ghttp.Server

This commit is contained in:
John
2019-08-06 20:40:04 +08:00
parent 2911ebb5d7
commit 77d9e472b7
12 changed files with 377 additions and 146 deletions

View File

@ -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

View File

@ -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)
})

View File

@ -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 {
// 注意排序函数的逻辑,从小到达排序

View File

@ -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...)
}
}

View File

@ -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 {
// 静态目录

View File

@ -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
}
// 判断给定对象是否控制器对象:

View File

@ -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,

View File

@ -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)
}
// 钩子函数存在性判断

View File

@ -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)

View 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")
})
}

View File

@ -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{

View File

@ -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")
},
})