github.com/astaxie/beego@v1.12.3/namespace.go (about)

     1  // Copyright 2014 beego Author. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package beego
    16  
    17  import (
    18  	"net/http"
    19  	"strings"
    20  
    21  	beecontext "github.com/astaxie/beego/context"
    22  )
    23  
    24  type namespaceCond func(*beecontext.Context) bool
    25  
    26  // LinkNamespace used as link action
    27  type LinkNamespace func(*Namespace)
    28  
    29  // Namespace is store all the info
    30  type Namespace struct {
    31  	prefix   string
    32  	handlers *ControllerRegister
    33  }
    34  
    35  // NewNamespace get new Namespace
    36  func NewNamespace(prefix string, params ...LinkNamespace) *Namespace {
    37  	ns := &Namespace{
    38  		prefix:   prefix,
    39  		handlers: NewControllerRegister(),
    40  	}
    41  	for _, p := range params {
    42  		p(ns)
    43  	}
    44  	return ns
    45  }
    46  
    47  // Cond set condition function
    48  // if cond return true can run this namespace, else can't
    49  // usage:
    50  // ns.Cond(func (ctx *context.Context) bool{
    51  //       if ctx.Input.Domain() == "api.beego.me" {
    52  //         return true
    53  //       }
    54  //       return false
    55  //   })
    56  // Cond as the first filter
    57  func (n *Namespace) Cond(cond namespaceCond) *Namespace {
    58  	fn := func(ctx *beecontext.Context) {
    59  		if !cond(ctx) {
    60  			exception("405", ctx)
    61  		}
    62  	}
    63  	if v := n.handlers.filters[BeforeRouter]; len(v) > 0 {
    64  		mr := new(FilterRouter)
    65  		mr.tree = NewTree()
    66  		mr.pattern = "*"
    67  		mr.filterFunc = fn
    68  		mr.tree.AddRouter("*", true)
    69  		n.handlers.filters[BeforeRouter] = append([]*FilterRouter{mr}, v...)
    70  	} else {
    71  		n.handlers.InsertFilter("*", BeforeRouter, fn)
    72  	}
    73  	return n
    74  }
    75  
    76  // Filter add filter in the Namespace
    77  // action has before & after
    78  // FilterFunc
    79  // usage:
    80  // Filter("before", func (ctx *context.Context){
    81  //       _, ok := ctx.Input.Session("uid").(int)
    82  //       if !ok && ctx.Request.RequestURI != "/login" {
    83  //          ctx.Redirect(302, "/login")
    84  //        }
    85  //   })
    86  func (n *Namespace) Filter(action string, filter ...FilterFunc) *Namespace {
    87  	var a int
    88  	if action == "before" {
    89  		a = BeforeRouter
    90  	} else if action == "after" {
    91  		a = FinishRouter
    92  	}
    93  	for _, f := range filter {
    94  		n.handlers.InsertFilter("*", a, f)
    95  	}
    96  	return n
    97  }
    98  
    99  // Router same as beego.Rourer
   100  // refer: https://godoc.org/github.com/astaxie/beego#Router
   101  func (n *Namespace) Router(rootpath string, c ControllerInterface, mappingMethods ...string) *Namespace {
   102  	n.handlers.Add(rootpath, c, mappingMethods...)
   103  	return n
   104  }
   105  
   106  // AutoRouter same as beego.AutoRouter
   107  // refer: https://godoc.org/github.com/astaxie/beego#AutoRouter
   108  func (n *Namespace) AutoRouter(c ControllerInterface) *Namespace {
   109  	n.handlers.AddAuto(c)
   110  	return n
   111  }
   112  
   113  // AutoPrefix same as beego.AutoPrefix
   114  // refer: https://godoc.org/github.com/astaxie/beego#AutoPrefix
   115  func (n *Namespace) AutoPrefix(prefix string, c ControllerInterface) *Namespace {
   116  	n.handlers.AddAutoPrefix(prefix, c)
   117  	return n
   118  }
   119  
   120  // Get same as beego.Get
   121  // refer: https://godoc.org/github.com/astaxie/beego#Get
   122  func (n *Namespace) Get(rootpath string, f FilterFunc) *Namespace {
   123  	n.handlers.Get(rootpath, f)
   124  	return n
   125  }
   126  
   127  // Post same as beego.Post
   128  // refer: https://godoc.org/github.com/astaxie/beego#Post
   129  func (n *Namespace) Post(rootpath string, f FilterFunc) *Namespace {
   130  	n.handlers.Post(rootpath, f)
   131  	return n
   132  }
   133  
   134  // Delete same as beego.Delete
   135  // refer: https://godoc.org/github.com/astaxie/beego#Delete
   136  func (n *Namespace) Delete(rootpath string, f FilterFunc) *Namespace {
   137  	n.handlers.Delete(rootpath, f)
   138  	return n
   139  }
   140  
   141  // Put same as beego.Put
   142  // refer: https://godoc.org/github.com/astaxie/beego#Put
   143  func (n *Namespace) Put(rootpath string, f FilterFunc) *Namespace {
   144  	n.handlers.Put(rootpath, f)
   145  	return n
   146  }
   147  
   148  // Head same as beego.Head
   149  // refer: https://godoc.org/github.com/astaxie/beego#Head
   150  func (n *Namespace) Head(rootpath string, f FilterFunc) *Namespace {
   151  	n.handlers.Head(rootpath, f)
   152  	return n
   153  }
   154  
   155  // Options same as beego.Options
   156  // refer: https://godoc.org/github.com/astaxie/beego#Options
   157  func (n *Namespace) Options(rootpath string, f FilterFunc) *Namespace {
   158  	n.handlers.Options(rootpath, f)
   159  	return n
   160  }
   161  
   162  // Patch same as beego.Patch
   163  // refer: https://godoc.org/github.com/astaxie/beego#Patch
   164  func (n *Namespace) Patch(rootpath string, f FilterFunc) *Namespace {
   165  	n.handlers.Patch(rootpath, f)
   166  	return n
   167  }
   168  
   169  // Any same as beego.Any
   170  // refer: https://godoc.org/github.com/astaxie/beego#Any
   171  func (n *Namespace) Any(rootpath string, f FilterFunc) *Namespace {
   172  	n.handlers.Any(rootpath, f)
   173  	return n
   174  }
   175  
   176  // Handler same as beego.Handler
   177  // refer: https://godoc.org/github.com/astaxie/beego#Handler
   178  func (n *Namespace) Handler(rootpath string, h http.Handler) *Namespace {
   179  	n.handlers.Handler(rootpath, h)
   180  	return n
   181  }
   182  
   183  // Include add include class
   184  // refer: https://godoc.org/github.com/astaxie/beego#Include
   185  func (n *Namespace) Include(cList ...ControllerInterface) *Namespace {
   186  	n.handlers.Include(cList...)
   187  	return n
   188  }
   189  
   190  // Namespace add nest Namespace
   191  // usage:
   192  //ns := beego.NewNamespace(“/v1”).
   193  //Namespace(
   194  //    beego.NewNamespace("/shop").
   195  //        Get("/:id", func(ctx *context.Context) {
   196  //            ctx.Output.Body([]byte("shopinfo"))
   197  //    }),
   198  //    beego.NewNamespace("/order").
   199  //        Get("/:id", func(ctx *context.Context) {
   200  //            ctx.Output.Body([]byte("orderinfo"))
   201  //    }),
   202  //    beego.NewNamespace("/crm").
   203  //        Get("/:id", func(ctx *context.Context) {
   204  //            ctx.Output.Body([]byte("crminfo"))
   205  //    }),
   206  //)
   207  func (n *Namespace) Namespace(ns ...*Namespace) *Namespace {
   208  	for _, ni := range ns {
   209  		for k, v := range ni.handlers.routers {
   210  			if _, ok := n.handlers.routers[k]; ok {
   211  				addPrefix(v, ni.prefix)
   212  				n.handlers.routers[k].AddTree(ni.prefix, v)
   213  			} else {
   214  				t := NewTree()
   215  				t.AddTree(ni.prefix, v)
   216  				addPrefix(t, ni.prefix)
   217  				n.handlers.routers[k] = t
   218  			}
   219  		}
   220  		if ni.handlers.enableFilter {
   221  			for pos, filterList := range ni.handlers.filters {
   222  				for _, mr := range filterList {
   223  					t := NewTree()
   224  					t.AddTree(ni.prefix, mr.tree)
   225  					mr.tree = t
   226  					n.handlers.insertFilterRouter(pos, mr)
   227  				}
   228  			}
   229  		}
   230  	}
   231  	return n
   232  }
   233  
   234  // AddNamespace register Namespace into beego.Handler
   235  // support multi Namespace
   236  func AddNamespace(nl ...*Namespace) {
   237  	for _, n := range nl {
   238  		for k, v := range n.handlers.routers {
   239  			if _, ok := BeeApp.Handlers.routers[k]; ok {
   240  				addPrefix(v, n.prefix)
   241  				BeeApp.Handlers.routers[k].AddTree(n.prefix, v)
   242  			} else {
   243  				t := NewTree()
   244  				t.AddTree(n.prefix, v)
   245  				addPrefix(t, n.prefix)
   246  				BeeApp.Handlers.routers[k] = t
   247  			}
   248  		}
   249  		if n.handlers.enableFilter {
   250  			for pos, filterList := range n.handlers.filters {
   251  				for _, mr := range filterList {
   252  					t := NewTree()
   253  					t.AddTree(n.prefix, mr.tree)
   254  					mr.tree = t
   255  					BeeApp.Handlers.insertFilterRouter(pos, mr)
   256  				}
   257  			}
   258  		}
   259  	}
   260  }
   261  
   262  func addPrefix(t *Tree, prefix string) {
   263  	for _, v := range t.fixrouters {
   264  		addPrefix(v, prefix)
   265  	}
   266  	if t.wildcard != nil {
   267  		addPrefix(t.wildcard, prefix)
   268  	}
   269  	for _, l := range t.leaves {
   270  		if c, ok := l.runObject.(*ControllerInfo); ok {
   271  			if !strings.HasPrefix(c.pattern, prefix) {
   272  				c.pattern = prefix + c.pattern
   273  			}
   274  		}
   275  	}
   276  }
   277  
   278  // NSCond is Namespace Condition
   279  func NSCond(cond namespaceCond) LinkNamespace {
   280  	return func(ns *Namespace) {
   281  		ns.Cond(cond)
   282  	}
   283  }
   284  
   285  // NSBefore Namespace BeforeRouter filter
   286  func NSBefore(filterList ...FilterFunc) LinkNamespace {
   287  	return func(ns *Namespace) {
   288  		ns.Filter("before", filterList...)
   289  	}
   290  }
   291  
   292  // NSAfter add Namespace FinishRouter filter
   293  func NSAfter(filterList ...FilterFunc) LinkNamespace {
   294  	return func(ns *Namespace) {
   295  		ns.Filter("after", filterList...)
   296  	}
   297  }
   298  
   299  // NSInclude Namespace Include ControllerInterface
   300  func NSInclude(cList ...ControllerInterface) LinkNamespace {
   301  	return func(ns *Namespace) {
   302  		ns.Include(cList...)
   303  	}
   304  }
   305  
   306  // NSRouter call Namespace Router
   307  func NSRouter(rootpath string, c ControllerInterface, mappingMethods ...string) LinkNamespace {
   308  	return func(ns *Namespace) {
   309  		ns.Router(rootpath, c, mappingMethods...)
   310  	}
   311  }
   312  
   313  // NSGet call Namespace Get
   314  func NSGet(rootpath string, f FilterFunc) LinkNamespace {
   315  	return func(ns *Namespace) {
   316  		ns.Get(rootpath, f)
   317  	}
   318  }
   319  
   320  // NSPost call Namespace Post
   321  func NSPost(rootpath string, f FilterFunc) LinkNamespace {
   322  	return func(ns *Namespace) {
   323  		ns.Post(rootpath, f)
   324  	}
   325  }
   326  
   327  // NSHead call Namespace Head
   328  func NSHead(rootpath string, f FilterFunc) LinkNamespace {
   329  	return func(ns *Namespace) {
   330  		ns.Head(rootpath, f)
   331  	}
   332  }
   333  
   334  // NSPut call Namespace Put
   335  func NSPut(rootpath string, f FilterFunc) LinkNamespace {
   336  	return func(ns *Namespace) {
   337  		ns.Put(rootpath, f)
   338  	}
   339  }
   340  
   341  // NSDelete call Namespace Delete
   342  func NSDelete(rootpath string, f FilterFunc) LinkNamespace {
   343  	return func(ns *Namespace) {
   344  		ns.Delete(rootpath, f)
   345  	}
   346  }
   347  
   348  // NSAny call Namespace Any
   349  func NSAny(rootpath string, f FilterFunc) LinkNamespace {
   350  	return func(ns *Namespace) {
   351  		ns.Any(rootpath, f)
   352  	}
   353  }
   354  
   355  // NSOptions call Namespace Options
   356  func NSOptions(rootpath string, f FilterFunc) LinkNamespace {
   357  	return func(ns *Namespace) {
   358  		ns.Options(rootpath, f)
   359  	}
   360  }
   361  
   362  // NSPatch call Namespace Patch
   363  func NSPatch(rootpath string, f FilterFunc) LinkNamespace {
   364  	return func(ns *Namespace) {
   365  		ns.Patch(rootpath, f)
   366  	}
   367  }
   368  
   369  // NSAutoRouter call Namespace AutoRouter
   370  func NSAutoRouter(c ControllerInterface) LinkNamespace {
   371  	return func(ns *Namespace) {
   372  		ns.AutoRouter(c)
   373  	}
   374  }
   375  
   376  // NSAutoPrefix call Namespace AutoPrefix
   377  func NSAutoPrefix(prefix string, c ControllerInterface) LinkNamespace {
   378  	return func(ns *Namespace) {
   379  		ns.AutoPrefix(prefix, c)
   380  	}
   381  }
   382  
   383  // NSNamespace add sub Namespace
   384  func NSNamespace(prefix string, params ...LinkNamespace) LinkNamespace {
   385  	return func(ns *Namespace) {
   386  		n := NewNamespace(prefix, params...)
   387  		ns.Namespace(n)
   388  	}
   389  }
   390  
   391  // NSHandler add handler
   392  func NSHandler(rootpath string, h http.Handler) LinkNamespace {
   393  	return func(ns *Namespace) {
   394  		ns.Handler(rootpath, h)
   395  	}
   396  }