mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
improve router group for duplicated router registering for package ghttp.Server
This commit is contained in:
@ -462,39 +462,3 @@ func Test_IsNil(t *testing.T) {
|
||||
gtest.Assert(j.IsNil(), true)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ToStructDeep(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
type Item struct {
|
||||
Title string `json:"title"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
type M struct {
|
||||
Id string `json:"id"`
|
||||
Me map[string]interface{} `json:"me"`
|
||||
Txt string `json:"txt"`
|
||||
Items []*Item `json:"items"`
|
||||
}
|
||||
|
||||
txt := `{
|
||||
"id":"88888",
|
||||
"me":{"name":"mikey","day":"20009"},
|
||||
"txt":"hello",
|
||||
"items":null
|
||||
}`
|
||||
|
||||
j, err := gjson.LoadContent(txt)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.GetString("me.name"), "mikey")
|
||||
gtest.Assert(j.GetString("items"), "")
|
||||
gtest.Assert(j.GetBool("items"), false)
|
||||
gtest.Assert(j.GetArray("items"), nil)
|
||||
m := new(M)
|
||||
err = j.ToStructDeep(m)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.AssertNE(m.Me, nil)
|
||||
gtest.Assert(m.Me["day"], "20009")
|
||||
gtest.Assert(m.Items, nil)
|
||||
})
|
||||
}
|
||||
|
||||
132
encoding/gjson/gjson_z_unit_struct_test.go
Normal file
132
encoding/gjson/gjson_z_unit_struct_test.go
Normal file
@ -0,0 +1,132 @@
|
||||
// Copyright 2017 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 gjson_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/encoding/gjson"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_ToStruct1(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
type BaseInfoItem struct {
|
||||
IdCardNumber string `db:"id_card_number" json:"idCardNumber" field:"id_card_number"`
|
||||
IsHouseholder bool `db:"is_householder" json:"isHouseholder" field:"is_householder"`
|
||||
HouseholderRelation string `db:"householder_relation" json:"householderRelation" field:"householder_relation"`
|
||||
UserName string `db:"user_name" json:"userName" field:"user_name"`
|
||||
UserSex string `db:"user_sex" json:"userSex" field:"user_sex"`
|
||||
UserAge int `db:"user_age" json:"userAge" field:"user_age"`
|
||||
UserNation string `db:"user_nation" json:"userNation" field:"user_nation"`
|
||||
}
|
||||
|
||||
type UserCollectionAddReq struct {
|
||||
BaseInfo []BaseInfoItem `db:"_" json:"baseInfo" field:"_"`
|
||||
}
|
||||
jsonContent := `{
|
||||
"baseInfo": [{
|
||||
"idCardNumber": "520101199412141111",
|
||||
"isHouseholder": true,
|
||||
"householderRelation": "户主",
|
||||
"userName": "李四",
|
||||
"userSex": "男",
|
||||
"userAge": 32,
|
||||
"userNation": "苗族",
|
||||
"userPhone": "13084183323",
|
||||
"liveAddress": {},
|
||||
"occupationInfo": [{
|
||||
"occupationType": "经商",
|
||||
"occupationBusinessInfo": [{
|
||||
"occupationClass": "制造业",
|
||||
"businessLicenseNumber": "32020000012300",
|
||||
"businessName": "土灶柴火鸡",
|
||||
"spouseName": "",
|
||||
"spouseIdCardNumber": "",
|
||||
"businessLicensePhotoId": 125,
|
||||
"businessPlace": "租赁房产",
|
||||
"hasGoodsInsurance": true,
|
||||
"businessScopeStr": "柴火鸡;烧烤",
|
||||
"businessAddress": {},
|
||||
"businessPerformAbility": {
|
||||
"businessType": "服务业",
|
||||
"businessLife": 5,
|
||||
"salesRevenue": 8000,
|
||||
"familyEquity": 6000
|
||||
}
|
||||
}],
|
||||
"occupationWorkInfo": {
|
||||
"occupationClass": "",
|
||||
"companyName": "",
|
||||
"companyType": "",
|
||||
"workYearNum": 0,
|
||||
"spouseName": "",
|
||||
"spouseIdCardNumber": "",
|
||||
"spousePhone": "",
|
||||
"spouseEducation": "",
|
||||
"spouseCompanyName": "",
|
||||
"workLevel": "",
|
||||
"workAddress": {},
|
||||
"workPerformAbility": {
|
||||
"familyAnnualIncome": 0,
|
||||
"familyEquity": 0,
|
||||
"workCooperationState": "",
|
||||
"workMoneyCooperationState": ""
|
||||
}
|
||||
},
|
||||
"occupationAgricultureInfo": []
|
||||
}],
|
||||
"assetsInfo": [],
|
||||
"expenditureInfo": [],
|
||||
"incomeInfo": [],
|
||||
"liabilityInfo": []
|
||||
}]
|
||||
}`
|
||||
data := new(UserCollectionAddReq)
|
||||
j, err := gjson.LoadJson(jsonContent)
|
||||
gtest.Assert(err, nil)
|
||||
err = j.ToStruct(data)
|
||||
gtest.Assert(err, nil)
|
||||
g.Dump(data)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ToStructDeep(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
type Item struct {
|
||||
Title string `json:"title"`
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
type M struct {
|
||||
Id string `json:"id"`
|
||||
Me map[string]interface{} `json:"me"`
|
||||
Txt string `json:"txt"`
|
||||
Items []*Item `json:"items"`
|
||||
}
|
||||
|
||||
txt := `{
|
||||
"id":"88888",
|
||||
"me":{"name":"mikey","day":"20009"},
|
||||
"txt":"hello",
|
||||
"items":null
|
||||
}`
|
||||
|
||||
j, err := gjson.LoadContent(txt)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(j.GetString("me.name"), "mikey")
|
||||
gtest.Assert(j.GetString("items"), "")
|
||||
gtest.Assert(j.GetBool("items"), false)
|
||||
gtest.Assert(j.GetArray("items"), nil)
|
||||
m := new(M)
|
||||
err = j.ToStructDeep(m)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.AssertNE(m.Me, nil)
|
||||
gtest.Assert(m.Me["day"], "20009")
|
||||
gtest.Assert(m.Items, nil)
|
||||
})
|
||||
}
|
||||
@ -8,9 +8,7 @@ package gmvc
|
||||
|
||||
import "github.com/gogf/gf/database/gdb"
|
||||
|
||||
// M is alias for Model,
|
||||
// just for short write purpose.
|
||||
type M = Model
|
||||
|
||||
// Model is alias for *gdb.Model.
|
||||
type Model = *gdb.Model
|
||||
type (
|
||||
M = Model // M is alias for Model, just for short write purpose.
|
||||
Model = *gdb.Model // Model is alias for *gdb.Model.
|
||||
)
|
||||
|
||||
@ -89,6 +89,7 @@ type (
|
||||
ctrlInfo *handlerController // Controller information for reflect usage.
|
||||
hookName string // Hook type name.
|
||||
router *Router // Router object.
|
||||
source string // Source file path:line when registering.
|
||||
}
|
||||
|
||||
// handlerParsedItem is the item parsed from URL.Path.
|
||||
@ -105,7 +106,7 @@ type (
|
||||
|
||||
// registeredRouteItem stores the information of the router and is used for route map.
|
||||
registeredRouteItem struct {
|
||||
file string // Source file path and its line number.
|
||||
source string // Source file path and its line number.
|
||||
handler *handlerItem // Handler object.
|
||||
}
|
||||
|
||||
|
||||
@ -12,121 +12,148 @@ import (
|
||||
|
||||
// 域名管理器对象
|
||||
type Domain struct {
|
||||
s *Server // 所属Server
|
||||
m map[string]bool // 多域名
|
||||
server *Server // 所属Server
|
||||
domains map[string]struct{} // 多域名
|
||||
}
|
||||
|
||||
// 生成一个域名对象, 参数 domains 支持给定多个域名。
|
||||
func (s *Server) Domain(domains string) *Domain {
|
||||
d := &Domain{
|
||||
s: s,
|
||||
m: make(map[string]bool),
|
||||
server: s,
|
||||
domains: make(map[string]struct{}),
|
||||
}
|
||||
for _, v := range strings.Split(domains, ",") {
|
||||
d.m[strings.TrimSpace(v)] = true
|
||||
d.domains[strings.TrimSpace(v)] = struct{}{}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Domain) BindHandler(pattern string, handler HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindHandler(pattern+"@"+domain, handler)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindHandler(pattern+"@"+domain, handler)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindHandler(pattern string, handler HandlerFunc, middleware []HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.doBindHandler(pattern+"@"+domain, handler, middleware)
|
||||
func (d *Domain) doBindHandler(
|
||||
pattern string, handler HandlerFunc,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindHandler(pattern+"@"+domain, handler, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindObject(pattern string, obj interface{}, methods ...string) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindObject(pattern+"@"+domain, obj, methods...)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindObject(pattern+"@"+domain, obj, methods...)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindObject(pattern string, obj interface{}, methods string, middleware []HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.doBindObject(pattern+"@"+domain, obj, methods, middleware)
|
||||
func (d *Domain) doBindObject(
|
||||
pattern string, obj interface{}, methods string,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindObject(pattern+"@"+domain, obj, methods, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindObjectMethod(pattern string, obj interface{}, method string) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindObjectMethod(pattern+"@"+domain, obj, method)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindObjectMethod(pattern+"@"+domain, obj, method)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindObjectMethod(pattern string, obj interface{}, method string, middleware []HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.doBindObjectMethod(pattern+"@"+domain, obj, method, middleware)
|
||||
func (d *Domain) doBindObjectMethod(
|
||||
pattern string, obj interface{}, method string,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindObjectMethod(pattern+"@"+domain, obj, method, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindObjectRest(pattern string, obj interface{}) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindObjectRest(pattern+"@"+domain, obj)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindObjectRest(pattern+"@"+domain, obj)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindObjectRest(pattern string, obj interface{}, middleware []HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.doBindObjectRest(pattern+"@"+domain, obj, middleware)
|
||||
func (d *Domain) doBindObjectRest(
|
||||
pattern string, obj interface{},
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindObjectRest(pattern+"@"+domain, obj, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindController(pattern string, c Controller, methods ...string) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindController(pattern+"@"+domain, c, methods...)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindController(pattern+"@"+domain, c, methods...)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindController(pattern string, c Controller, methods string, middleware []HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.doBindController(pattern+"@"+domain, c, methods, middleware)
|
||||
func (d *Domain) doBindController(
|
||||
pattern string, c Controller, methods string,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindController(pattern+"@"+domain, c, methods, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindControllerMethod(pattern string, c Controller, method string) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindControllerMethod(pattern+"@"+domain, c, method)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindControllerMethod(pattern+"@"+domain, c, method)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindControllerMethod(pattern string, c Controller, method string, middleware []HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.doBindControllerMethod(pattern+"@"+domain, c, method, middleware)
|
||||
func (d *Domain) doBindControllerMethod(
|
||||
pattern string, c Controller, method string,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindControllerMethod(pattern+"@"+domain, c, method, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindControllerRest(pattern string, c Controller) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindControllerRest(pattern+"@"+domain, c)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindControllerRest(pattern+"@"+domain, c)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindControllerRest(pattern string, c Controller, middleware []HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.doBindControllerRest(pattern+"@"+domain, c, middleware)
|
||||
func (d *Domain) doBindControllerRest(
|
||||
pattern string, c Controller,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindControllerRest(pattern+"@"+domain, c, middleware, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindHookHandler(pattern string, hook string, handler HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindHookHandler(pattern+"@"+domain, hook, handler)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindHookHandler(pattern+"@"+domain, hook, handler)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) doBindHookHandler(pattern string, hook string, handler HandlerFunc, source string) {
|
||||
for domain, _ := range d.domains {
|
||||
d.server.doBindHookHandler(pattern+"@"+domain, hook, handler, source)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindHookHandlerByMap(pattern string, hookmap map[string]HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindHookHandlerByMap(pattern+"@"+domain, hookmap)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindHookHandlerByMap(pattern+"@"+domain, hookmap)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindStatusHandler(status int, handler HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.setStatusHandler(d.s.statusHandlerKey(status, domain), handler)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.setStatusHandler(d.server.statusHandlerKey(status, domain), handler)
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,14 +164,14 @@ func (d *Domain) BindStatusHandlerByMap(handlerMap map[int]HandlerFunc) {
|
||||
}
|
||||
|
||||
func (d *Domain) BindMiddleware(pattern string, handlers ...HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindMiddleware(pattern+"@"+domain, handlers...)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindMiddleware(pattern+"@"+domain, handlers...)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Domain) BindMiddlewareDefault(handlers ...HandlerFunc) {
|
||||
for domain, _ := range d.m {
|
||||
d.s.BindMiddleware(gDEFAULT_MIDDLEWARE_PATTERN+"@"+domain, handlers...)
|
||||
for domain, _ := range d.domains {
|
||||
d.server.BindMiddleware(gDEFAULT_MIDDLEWARE_PATTERN+"@"+domain, handlers...)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -67,6 +67,10 @@ func (s *Server) parsePattern(pattern string) (domain, method, path string, err
|
||||
// is the well designed router storage structure for router searching when the request is under serving.
|
||||
func (s *Server) setHandler(pattern string, handler *handlerItem) {
|
||||
handler.itemId = handlerIdGenerator.Add(1)
|
||||
if handler.source == "" {
|
||||
_, file, line := gdebug.CallerWithFilter(gFILTER_KEY)
|
||||
handler.source = fmt.Sprintf(`%s:%d`, file, line)
|
||||
}
|
||||
domain, method, uri, err := s.parsePattern(pattern)
|
||||
if err != nil {
|
||||
s.Logger().Fatal("invalid pattern:", pattern, err)
|
||||
@ -83,7 +87,10 @@ func (s *Server) setHandler(pattern string, handler *handlerItem) {
|
||||
switch handler.itemType {
|
||||
case gHANDLER_TYPE_HANDLER, gHANDLER_TYPE_OBJECT, gHANDLER_TYPE_CONTROLLER:
|
||||
if item, ok := s.routesMap[routerKey]; ok {
|
||||
s.Logger().Fatalf(`duplicated route registry "%s", already registered at %s`, pattern, item[0].file)
|
||||
s.Logger().Fatalf(
|
||||
`duplicated route registry "%s" at %s , already registered at %s`,
|
||||
pattern, handler.source, item[0].source,
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -184,9 +191,9 @@ func (s *Server) setHandler(pattern string, handler *handlerItem) {
|
||||
if _, ok := s.routesMap[routerKey]; !ok {
|
||||
s.routesMap[routerKey] = make([]registeredRouteItem, 0)
|
||||
}
|
||||
_, file, line := gdebug.CallerWithFilter(gFILTER_KEY)
|
||||
|
||||
routeItem := registeredRouteItem{
|
||||
file: fmt.Sprintf(`%s:%d`, file, line),
|
||||
source: handler.source,
|
||||
handler: handler,
|
||||
}
|
||||
switch handler.itemType {
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/debug/gdebug"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
@ -36,6 +38,7 @@ type (
|
||||
pattern string
|
||||
object interface{} // Can be handler, controller or object.
|
||||
params []interface{} // Extra parameters for route registering depending on the type.
|
||||
source string // // Handler is register at certain source file path:line.
|
||||
}
|
||||
)
|
||||
|
||||
@ -53,10 +56,10 @@ func (s *Server) handlePreBindItems() {
|
||||
if item.group.server != nil && item.group.server != s {
|
||||
continue
|
||||
}
|
||||
if item.group.domain != nil && item.group.domain.s != s {
|
||||
if item.group.domain != nil && item.group.domain.server != s {
|
||||
continue
|
||||
}
|
||||
item.group.doBind(item.bindType, item.pattern, item.object, item.params...)
|
||||
item.group.doBindRoutersToServer(item)
|
||||
}
|
||||
preBindItems = preBindItems[:0]
|
||||
}
|
||||
@ -147,9 +150,9 @@ func (g *RouterGroup) Bind(items []GroupItem) *RouterGroup {
|
||||
bindType := gstr.ToUpper(gconv.String(item[0]))
|
||||
switch bindType {
|
||||
case "REST":
|
||||
group.preBind("REST", gconv.String(item[0])+":"+gconv.String(item[1]), item[2])
|
||||
group.preBindToLocalArray("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])
|
||||
group.preBindToLocalArray("MIDDLEWARE", gconv.String(item[0])+":"+gconv.String(item[1]), item[2])
|
||||
default:
|
||||
if strings.EqualFold(bindType, "ALL") {
|
||||
bindType = ""
|
||||
@ -157,9 +160,9 @@ func (g *RouterGroup) Bind(items []GroupItem) *RouterGroup {
|
||||
bindType += ":"
|
||||
}
|
||||
if len(item) > 3 {
|
||||
group.preBind("HANDLER", bindType+gconv.String(item[1]), item[2], item[3])
|
||||
group.preBindToLocalArray("HANDLER", bindType+gconv.String(item[1]), item[2], item[3])
|
||||
} else {
|
||||
group.preBind("HANDLER", bindType+gconv.String(item[1]), item[2])
|
||||
group.preBindToLocalArray("HANDLER", bindType+gconv.String(item[1]), item[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -168,62 +171,62 @@ func (g *RouterGroup) Bind(items []GroupItem) *RouterGroup {
|
||||
|
||||
// ALL registers a http handler to given route pattern and all http methods.
|
||||
func (g *RouterGroup) ALL(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", gDEFAULT_METHOD+":"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", gDEFAULT_METHOD+":"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// GET registers a http handler to given route pattern and http method: GET.
|
||||
func (g *RouterGroup) GET(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "GET:"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", "GET:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// PUT registers a http handler to given route pattern and http method: PUT.
|
||||
func (g *RouterGroup) PUT(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "PUT:"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", "PUT:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// POST registers a http handler to given route pattern and http method: POST.
|
||||
func (g *RouterGroup) POST(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "POST:"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", "POST:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// DELETE registers a http handler to given route pattern and http method: DELETE.
|
||||
func (g *RouterGroup) DELETE(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "DELETE:"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", "DELETE:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// PATCH registers a http handler to given route pattern and http method: PATCH.
|
||||
func (g *RouterGroup) PATCH(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "PATCH:"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", "PATCH:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// HEAD registers a http handler to given route pattern and http method: HEAD.
|
||||
func (g *RouterGroup) HEAD(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "HEAD:"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", "HEAD:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// CONNECT registers a http handler to given route pattern and http method: CONNECT.
|
||||
func (g *RouterGroup) CONNECT(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "CONNECT:"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", "CONNECT:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// OPTIONS registers a http handler to given route pattern and http method: OPTIONS.
|
||||
func (g *RouterGroup) OPTIONS(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "OPTIONS:"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", "OPTIONS:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// TRACE registers a http handler to given route pattern and http method: TRACE.
|
||||
func (g *RouterGroup) TRACE(pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", "TRACE:"+pattern, object, params...)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", "TRACE:"+pattern, object, params...)
|
||||
}
|
||||
|
||||
// REST registers a http handler to given route pattern according to REST rule.
|
||||
func (g *RouterGroup) REST(pattern string, object interface{}) *RouterGroup {
|
||||
return g.Clone().preBind("REST", pattern, object)
|
||||
return g.Clone().preBindToLocalArray("REST", pattern, object)
|
||||
}
|
||||
|
||||
// Hook registers a hook to given route pattern.
|
||||
func (g *RouterGroup) Hook(pattern string, hook string, handler HandlerFunc) *RouterGroup {
|
||||
return g.Clone().preBind("HANDLER", pattern, handler, hook)
|
||||
return g.Clone().preBindToLocalArray("HANDLER", pattern, handler, hook)
|
||||
}
|
||||
|
||||
// Middleware binds one or more middleware to the router group.
|
||||
@ -232,14 +235,16 @@ func (g *RouterGroup) Middleware(handlers ...HandlerFunc) *RouterGroup {
|
||||
return g
|
||||
}
|
||||
|
||||
// preBind adds the route registering parameters to internal variable array for lazily registering feature.
|
||||
func (g *RouterGroup) preBind(bindType string, pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
// preBindToLocalArray adds the route registering parameters to internal variable array for lazily registering feature.
|
||||
func (g *RouterGroup) preBindToLocalArray(bindType string, pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
_, file, line := gdebug.CallerWithFilter(gFILTER_KEY)
|
||||
preBindItems = append(preBindItems, preBindItem{
|
||||
group: g,
|
||||
bindType: bindType,
|
||||
pattern: pattern,
|
||||
object: object,
|
||||
params: params,
|
||||
source: fmt.Sprintf(`%s:%d`, file, line),
|
||||
})
|
||||
return g
|
||||
}
|
||||
@ -255,8 +260,15 @@ func (g *RouterGroup) getPrefix() string {
|
||||
return prefix
|
||||
}
|
||||
|
||||
// doBind does really registering for the group.
|
||||
func (g *RouterGroup) doBind(bindType string, pattern string, object interface{}, params ...interface{}) *RouterGroup {
|
||||
// doBindRoutersToServer does really registering for the group.
|
||||
func (g *RouterGroup) doBindRoutersToServer(item preBindItem) *RouterGroup {
|
||||
var (
|
||||
bindType = item.bindType
|
||||
pattern = item.pattern
|
||||
object = item.object
|
||||
params = item.params
|
||||
source = item.source
|
||||
)
|
||||
prefix := g.getPrefix()
|
||||
// Route check.
|
||||
if len(prefix) > 0 {
|
||||
@ -271,7 +283,9 @@ func (g *RouterGroup) doBind(bindType string, pattern string, object interface{}
|
||||
if bindType == "REST" {
|
||||
pattern = prefix + "/" + strings.TrimLeft(path, "/")
|
||||
} else {
|
||||
pattern = g.server.serveHandlerKey(method, prefix+"/"+strings.TrimLeft(path, "/"), domain)
|
||||
pattern = g.server.serveHandlerKey(
|
||||
method, prefix+"/"+strings.TrimLeft(path, "/"), domain,
|
||||
)
|
||||
}
|
||||
}
|
||||
// Filter repeated char '/'.
|
||||
@ -286,78 +300,102 @@ func (g *RouterGroup) doBind(bindType string, pattern string, object interface{}
|
||||
case "HANDLER":
|
||||
if h, ok := object.(HandlerFunc); ok {
|
||||
if g.server != nil {
|
||||
g.server.doBindHandler(pattern, h, g.middleware)
|
||||
g.server.doBindHandler(pattern, h, g.middleware, source)
|
||||
} else {
|
||||
g.domain.doBindHandler(pattern, h, g.middleware)
|
||||
g.domain.doBindHandler(pattern, h, g.middleware, source)
|
||||
}
|
||||
} else if g.isController(object) {
|
||||
if len(extras) > 0 {
|
||||
if g.server != nil {
|
||||
if gstr.Contains(extras[0], ",") {
|
||||
g.server.doBindController(pattern, object.(Controller), extras[0], g.middleware)
|
||||
g.server.doBindController(
|
||||
pattern, object.(Controller), extras[0], g.middleware, source,
|
||||
)
|
||||
} else {
|
||||
g.server.doBindControllerMethod(pattern, object.(Controller), extras[0], g.middleware)
|
||||
g.server.doBindControllerMethod(
|
||||
pattern, object.(Controller), extras[0], g.middleware, source,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if gstr.Contains(extras[0], ",") {
|
||||
g.domain.doBindController(pattern, object.(Controller), extras[0], g.middleware)
|
||||
g.domain.doBindController(
|
||||
pattern, object.(Controller), extras[0], g.middleware, source,
|
||||
)
|
||||
} else {
|
||||
g.domain.doBindControllerMethod(pattern, object.(Controller), extras[0], g.middleware)
|
||||
g.domain.doBindControllerMethod(
|
||||
pattern, object.(Controller), extras[0], g.middleware, source,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if g.server != nil {
|
||||
g.server.doBindController(pattern, object.(Controller), "", g.middleware)
|
||||
g.server.doBindController(
|
||||
pattern, object.(Controller), "", g.middleware, source,
|
||||
)
|
||||
} else {
|
||||
g.domain.doBindController(pattern, object.(Controller), "", g.middleware)
|
||||
g.domain.doBindController(
|
||||
pattern, object.(Controller), "", g.middleware, source,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(extras) > 0 {
|
||||
if g.server != nil {
|
||||
if gstr.Contains(extras[0], ",") {
|
||||
g.server.doBindObject(pattern, object, extras[0], g.middleware)
|
||||
g.server.doBindObject(
|
||||
pattern, object, extras[0], g.middleware, source,
|
||||
)
|
||||
} else {
|
||||
g.server.doBindObjectMethod(pattern, object, extras[0], g.middleware)
|
||||
g.server.doBindObjectMethod(
|
||||
pattern, object, extras[0], g.middleware, source,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if gstr.Contains(extras[0], ",") {
|
||||
g.domain.doBindObject(pattern, object, extras[0], g.middleware)
|
||||
g.domain.doBindObject(
|
||||
pattern, object, extras[0], g.middleware, source,
|
||||
)
|
||||
} else {
|
||||
g.domain.doBindObjectMethod(pattern, object, extras[0], g.middleware)
|
||||
g.domain.doBindObjectMethod(
|
||||
pattern, object, extras[0], g.middleware, source,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if g.server != nil {
|
||||
g.server.doBindObject(pattern, object, "", g.middleware)
|
||||
g.server.doBindObject(pattern, object, "", g.middleware, source)
|
||||
} else {
|
||||
g.domain.doBindObject(pattern, object, "", g.middleware)
|
||||
g.domain.doBindObject(pattern, object, "", g.middleware, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
case "REST":
|
||||
if g.isController(object) {
|
||||
if g.server != nil {
|
||||
g.server.doBindControllerRest(pattern, object.(Controller), g.middleware)
|
||||
g.server.doBindControllerRest(
|
||||
pattern, object.(Controller), g.middleware, source,
|
||||
)
|
||||
} else {
|
||||
g.domain.doBindControllerRest(pattern, object.(Controller), g.middleware)
|
||||
g.domain.doBindControllerRest(
|
||||
pattern, object.(Controller), g.middleware, source,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if g.server != nil {
|
||||
g.server.doBindObjectRest(pattern, object, g.middleware)
|
||||
g.server.doBindObjectRest(pattern, object, g.middleware, source)
|
||||
} else {
|
||||
g.domain.doBindObjectRest(pattern, object, g.middleware)
|
||||
g.domain.doBindObjectRest(pattern, object, g.middleware, source)
|
||||
}
|
||||
}
|
||||
case "HOOK":
|
||||
if h, ok := object.(HandlerFunc); ok {
|
||||
if g.server != nil {
|
||||
g.server.BindHookHandler(pattern, extras[0], h)
|
||||
g.server.doBindHookHandler(pattern, extras[0], h, source)
|
||||
} else {
|
||||
g.domain.BindHookHandler(pattern, extras[0], h)
|
||||
g.domain.doBindHookHandler(pattern, extras[0], h, source)
|
||||
}
|
||||
} else {
|
||||
g.server.Logger().Fatalf("invalid hook handler for pattern:%s", pattern)
|
||||
g.server.Logger().Fatalf("invalid hook handler for pattern: %s", pattern)
|
||||
}
|
||||
}
|
||||
return g
|
||||
|
||||
@ -13,11 +13,16 @@ import (
|
||||
|
||||
// 绑定指定的hook回调函数, pattern参数同BindHandler,支持命名路由;hook参数的值由ghttp server设定,参数不区分大小写
|
||||
func (s *Server) BindHookHandler(pattern string, hook string, handler HandlerFunc) {
|
||||
s.doBindHookHandler(pattern, hook, handler, "")
|
||||
}
|
||||
|
||||
func (s *Server) doBindHookHandler(pattern string, hook string, handler HandlerFunc, source string) {
|
||||
s.setHandler(pattern, &handlerItem{
|
||||
itemType: gHANDLER_TYPE_HOOK,
|
||||
itemName: gdebug.FuncPath(handler),
|
||||
itemFunc: handler,
|
||||
hookName: hook,
|
||||
source: source,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -24,12 +24,12 @@ func (s *Server) BindController(pattern string, controller Controller, method ..
|
||||
if len(method) > 0 {
|
||||
bindMethod = method[0]
|
||||
}
|
||||
s.doBindController(pattern, controller, bindMethod, nil)
|
||||
s.doBindController(pattern, controller, bindMethod, nil, "")
|
||||
}
|
||||
|
||||
// 绑定路由到指定的方法执行, 第三个参数method仅支持一个方法注册,不支持多个,并且区分大小写。
|
||||
func (s *Server) BindControllerMethod(pattern string, controller Controller, method string) {
|
||||
s.doBindControllerMethod(pattern, controller, method, nil)
|
||||
s.doBindControllerMethod(pattern, controller, method, nil, "")
|
||||
}
|
||||
|
||||
// 绑定控制器(RESTFul),控制器需要实现gmvc.Controller接口
|
||||
@ -37,10 +37,13 @@ func (s *Server) BindControllerMethod(pattern string, controller Controller, met
|
||||
// 因此只会绑定HTTP Method对应的方法,其他方法不会自动注册绑定
|
||||
// 这种方式绑定的控制器每一次请求都会初始化一个新的控制器对象进行处理,对应不同的请求会话
|
||||
func (s *Server) BindControllerRest(pattern string, controller Controller) {
|
||||
s.doBindControllerRest(pattern, controller, nil)
|
||||
s.doBindControllerRest(pattern, controller, nil, "")
|
||||
}
|
||||
|
||||
func (s *Server) doBindController(pattern string, controller Controller, method string, middleware []HandlerFunc) {
|
||||
func (s *Server) doBindController(
|
||||
pattern string, controller Controller, method string,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
// Convert input method to map for convenience and high performance searching.
|
||||
var methodMap map[string]bool
|
||||
if len(method) > 0 {
|
||||
@ -98,6 +101,7 @@ func (s *Server) doBindController(pattern string, controller Controller, method
|
||||
reflect: v.Elem().Type(),
|
||||
},
|
||||
middleware: middleware,
|
||||
source: source,
|
||||
}
|
||||
// 如果方法中带有Index方法,那么额外自动增加一个路由规则匹配主URI,
|
||||
// 例如: pattern为/user, 那么会同时注册/user及/user/index,
|
||||
@ -117,13 +121,20 @@ func (s *Server) doBindController(pattern string, controller Controller, method
|
||||
reflect: v.Elem().Type(),
|
||||
},
|
||||
middleware: middleware,
|
||||
source: source,
|
||||
}
|
||||
}
|
||||
}
|
||||
s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
func (s *Server) doBindControllerMethod(pattern string, controller Controller, method string, middleware []HandlerFunc) {
|
||||
func (s *Server) doBindControllerMethod(
|
||||
pattern string,
|
||||
controller Controller,
|
||||
method string,
|
||||
middleware []HandlerFunc,
|
||||
source string,
|
||||
) {
|
||||
m := make(map[string]*handlerItem)
|
||||
v := reflect.ValueOf(controller)
|
||||
t := v.Type()
|
||||
@ -141,8 +152,10 @@ func (s *Server) doBindControllerMethod(pattern string, controller Controller, m
|
||||
ctlName = fmt.Sprintf(`(%s)`, ctlName)
|
||||
}
|
||||
if _, ok := methodValue.Interface().(func()); !ok {
|
||||
s.Logger().Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`,
|
||||
pkgPath, ctlName, methodName, methodValue.Type().String())
|
||||
s.Logger().Errorf(
|
||||
`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`,
|
||||
pkgPath, ctlName, methodName, methodValue.Type().String(),
|
||||
)
|
||||
return
|
||||
}
|
||||
key := s.mergeBuildInNameToPattern(pattern, structName, methodName, false)
|
||||
@ -154,11 +167,15 @@ func (s *Server) doBindControllerMethod(pattern string, controller Controller, m
|
||||
reflect: v.Elem().Type(),
|
||||
},
|
||||
middleware: middleware,
|
||||
source: source,
|
||||
}
|
||||
s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
func (s *Server) doBindControllerRest(pattern string, controller Controller, middleware []HandlerFunc) {
|
||||
func (s *Server) doBindControllerRest(
|
||||
pattern string, controller Controller,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
// 遍历控制器,获取方法列表,并构造成uri
|
||||
m := make(map[string]*handlerItem)
|
||||
v := reflect.ValueOf(controller)
|
||||
@ -177,8 +194,10 @@ func (s *Server) doBindControllerRest(pattern string, controller Controller, mid
|
||||
ctlName = fmt.Sprintf(`(%s)`, ctlName)
|
||||
}
|
||||
if _, ok := v.Method(i).Interface().(func()); !ok {
|
||||
s.Logger().Errorf(`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`,
|
||||
pkgPath, ctlName, methodName, v.Method(i).Type().String())
|
||||
s.Logger().Errorf(
|
||||
`invalid route method: %s.%s.%s defined as "%s", but "func()" is required for controller registry`,
|
||||
pkgPath, ctlName, methodName, v.Method(i).Type().String(),
|
||||
)
|
||||
return
|
||||
}
|
||||
key := s.mergeBuildInNameToPattern(methodName+":"+pattern, structName, methodName, false)
|
||||
@ -190,6 +209,7 @@ func (s *Server) doBindControllerRest(pattern string, controller Controller, mid
|
||||
reflect: v.Elem().Type(),
|
||||
},
|
||||
middleware: middleware,
|
||||
source: source,
|
||||
}
|
||||
}
|
||||
s.bindHandlerByMap(m)
|
||||
|
||||
@ -16,18 +16,22 @@ import (
|
||||
|
||||
// 注意该方法是直接绑定函数的内存地址,执行的时候直接执行该方法,不会存在初始化新的控制器逻辑
|
||||
func (s *Server) BindHandler(pattern string, handler HandlerFunc) {
|
||||
s.doBindHandler(pattern, handler, nil)
|
||||
s.doBindHandler(pattern, handler, nil, "")
|
||||
}
|
||||
|
||||
// 绑定URI到操作函数/方法
|
||||
// pattern的格式形如:/user/list, put:/user, delete:/user, post:/user@johng.cn
|
||||
// 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行
|
||||
func (s *Server) doBindHandler(pattern string, handler HandlerFunc, middleware []HandlerFunc) {
|
||||
func (s *Server) doBindHandler(
|
||||
pattern string, handler HandlerFunc,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
s.setHandler(pattern, &handlerItem{
|
||||
itemName: gdebug.FuncPath(handler),
|
||||
itemType: gHANDLER_TYPE_HANDLER,
|
||||
itemFunc: handler,
|
||||
middleware: middleware,
|
||||
source: source,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -23,22 +23,25 @@ func (s *Server) BindObject(pattern string, object interface{}, method ...string
|
||||
if len(method) > 0 {
|
||||
bindMethod = method[0]
|
||||
}
|
||||
s.doBindObject(pattern, object, bindMethod, nil)
|
||||
s.doBindObject(pattern, object, bindMethod, nil, "")
|
||||
}
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面,
|
||||
// 第三个参数method仅支持一个方法注册,不支持多个,并且区分大小写。
|
||||
func (s *Server) BindObjectMethod(pattern string, object interface{}, method string) {
|
||||
s.doBindObjectMethod(pattern, object, method, nil)
|
||||
s.doBindObjectMethod(pattern, object, method, nil, "")
|
||||
}
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面,
|
||||
// 需要注意对象方法的定义必须按照 ghttp.HandlerFunc 来定义
|
||||
func (s *Server) BindObjectRest(pattern string, object interface{}) {
|
||||
s.doBindObjectRest(pattern, object, nil)
|
||||
s.doBindObjectRest(pattern, object, nil, "")
|
||||
}
|
||||
|
||||
func (s *Server) doBindObject(pattern string, object interface{}, method string, middleware []HandlerFunc) {
|
||||
func (s *Server) doBindObject(
|
||||
pattern string, object interface{}, method string,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
// Convert input method to map for convenience and high performance searching purpose.
|
||||
var methodMap map[string]bool
|
||||
if len(method) > 0 {
|
||||
@ -107,6 +110,7 @@ func (s *Server) doBindObject(pattern string, object interface{}, method string,
|
||||
initFunc: initFunc,
|
||||
shutFunc: shutFunc,
|
||||
middleware: middleware,
|
||||
source: source,
|
||||
}
|
||||
// 如果方法中带有Index方法,那么额外自动增加一个路由规则匹配主URI。
|
||||
// 注意,当pattern带有内置变量时,不会自动加该路由。
|
||||
@ -123,6 +127,7 @@ func (s *Server) doBindObject(pattern string, object interface{}, method string,
|
||||
initFunc: initFunc,
|
||||
shutFunc: shutFunc,
|
||||
middleware: middleware,
|
||||
source: source,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -131,7 +136,10 @@ func (s *Server) doBindObject(pattern string, object interface{}, method string,
|
||||
|
||||
// 绑定对象到URI请求处理中,会自动识别方法名称,并附加到对应的URI地址后面,
|
||||
// 第三个参数method仅支持一个方法注册,不支持多个,并且区分大小写。
|
||||
func (s *Server) doBindObjectMethod(pattern string, object interface{}, method string, middleware []HandlerFunc) {
|
||||
func (s *Server) doBindObjectMethod(
|
||||
pattern string, object interface{}, method string,
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
m := make(map[string]*handlerItem)
|
||||
v := reflect.ValueOf(object)
|
||||
t := v.Type()
|
||||
@ -170,12 +178,16 @@ func (s *Server) doBindObjectMethod(pattern string, object interface{}, method s
|
||||
initFunc: initFunc,
|
||||
shutFunc: shutFunc,
|
||||
middleware: middleware,
|
||||
source: source,
|
||||
}
|
||||
|
||||
s.bindHandlerByMap(m)
|
||||
}
|
||||
|
||||
func (s *Server) doBindObjectRest(pattern string, object interface{}, middleware []HandlerFunc) {
|
||||
func (s *Server) doBindObjectRest(
|
||||
pattern string, object interface{},
|
||||
middleware []HandlerFunc, source string,
|
||||
) {
|
||||
m := make(map[string]*handlerItem)
|
||||
v := reflect.ValueOf(object)
|
||||
t := v.Type()
|
||||
@ -213,6 +225,7 @@ func (s *Server) doBindObjectRest(pattern string, object interface{}, middleware
|
||||
initFunc: initFunc,
|
||||
shutFunc: shutFunc,
|
||||
middleware: middleware,
|
||||
source: source,
|
||||
}
|
||||
}
|
||||
s.bindHandlerByMap(m)
|
||||
|
||||
@ -40,6 +40,7 @@ func Test_Middleware_CORS(t *testing.T) {
|
||||
resp, err := client.Get("/api.v2/user/list")
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(len(resp.Header["Access-Control-Allow-Headers"]), 0)
|
||||
gtest.Assert(resp.StatusCode, 404)
|
||||
resp.Close()
|
||||
|
||||
// POST request matches the route and CORS middleware.
|
||||
@ -61,6 +62,7 @@ func Test_Middleware_CORS(t *testing.T) {
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(len(resp.Header["Access-Control-Allow-Headers"]), 0)
|
||||
gtest.Assert(resp.ReadAllString(), "Not Found")
|
||||
gtest.Assert(resp.StatusCode, 404)
|
||||
resp.Close()
|
||||
})
|
||||
// OPTIONS POST
|
||||
@ -71,6 +73,7 @@ func Test_Middleware_CORS(t *testing.T) {
|
||||
resp, err := client.Options("/api.v2/user/list")
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(len(resp.Header["Access-Control-Allow-Headers"]), 1)
|
||||
gtest.Assert(resp.StatusCode, 200)
|
||||
resp.Close()
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user