From 66209cae4f8e3df669f9be0489f895a35819b9e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Meyer?= Date: Wed, 21 Feb 2018 08:18:53 +0300 Subject: [PATCH 1/5] Save Former-commit-id: 592e9cddf3511fc08e87f19ad39fdaac479b453f --- _examples/routing/route-state/main.go | 2 +- core/router/api_builder.go | 19 ++++++++++-- core/router/fallback_stack.go | 44 +++++++++++++++++++++++++++ core/router/handler.go | 9 ++++-- core/router/party.go | 7 +++++ mvc/mvc.go | 7 +++++ 6 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 core/router/fallback_stack.go diff --git a/_examples/routing/route-state/main.go b/_examples/routing/route-state/main.go index f85426f8..ec4f03db 100644 --- a/_examples/routing/route-state/main.go +++ b/_examples/routing/route-state/main.go @@ -8,7 +8,7 @@ func main() { app := iris.New() none := app.None("/invisible/{username}", func(ctx iris.Context) { - ctx.Writef("Hello %s with method: %s", ctx.Values().GetString("username"), ctx.Method()) + ctx.Writef("Hello %s with method: %s", ctx.Params().Get("username"), ctx.Method()) if from := ctx.Values().GetString("from"); from != "" { ctx.Writef("\nI see that you're coming from %s", from) diff --git a/core/router/api_builder.go b/core/router/api_builder.go index e9afefba..e0cfc4d7 100644 --- a/core/router/api_builder.go +++ b/core/router/api_builder.go @@ -90,6 +90,8 @@ type APIBuilder struct { doneHandlers context.Handlers // global done handlers, order doesn't matter doneGlobalHandlers context.Handlers + // fallback stack, LIFO order + fallbackStack *FallbackStack // the per-party relativePath string } @@ -106,6 +108,7 @@ func NewAPIBuilder() *APIBuilder { reporter: errors.NewReporter(), relativePath: "/", routes: new(repository), + fallbackStack: NewFallbackStack(), } return api @@ -268,9 +271,10 @@ func (api *APIBuilder) Party(relativePath string, handlers ...context.Handler) P doneGlobalHandlers: api.doneGlobalHandlers, reporter: api.reporter, // per-party/children - middleware: middleware, - doneHandlers: api.doneHandlers, - relativePath: fullpath, + middleware: middleware, + doneHandlers: api.doneHandlers, + fallbackStack: api.fallbackStack, + relativePath: fullpath, } } @@ -422,6 +426,15 @@ func (api *APIBuilder) DoneGlobal(handlers ...context.Handler) { api.doneGlobalHandlers = append(api.doneGlobalHandlers, handlers...) } +// Fallback appends Handler(s) to the current Party's fallback stack. +// Handler(s) is(are) called from Fallback stack when no route found and before sending NotFound status. +// Therefore Handler(s) in Fallback stack could send another thing than NotFound status, +// if `Context.Next()` method is not called. +// Done & DoneGlobal Handlers are not called. +func (api *APIBuilder) Fallback(middleware ...context.Handler) { + api.fallbackStack.add(middleware) +} + // Reset removes all the begin and done handlers that may derived from the parent party via `Use` & `Done`, // note that the `Reset` will not reset the handlers that are registered via `UseGlobal` & `DoneGlobal`. // diff --git a/core/router/fallback_stack.go b/core/router/fallback_stack.go new file mode 100644 index 00000000..499e0896 --- /dev/null +++ b/core/router/fallback_stack.go @@ -0,0 +1,44 @@ +package router + +import ( + "net/http" + "sync" + + "github.com/kataras/iris/context" +) + +type FallbackStack struct { + handlers context.Handlers + m sync.Mutex +} + +func (stk *FallbackStack) add(h context.Handlers) { + stk.m.Lock() + defer stk.m.Unlock() + + stk.handlers = append(stk.handlers, h...) + + copy(stk.handlers[len(h):], stk.handlers) + copy(stk.handlers, h) +} + +func (stk *FallbackStack) list() context.Handlers { + res := make(context.Handlers, len(stk.handlers)) + + stk.m.Lock() + defer stk.m.Unlock() + + copy(res, stk.handlers) + + return res +} + +func NewFallbackStack() *FallbackStack { + return &FallbackStack{ + handlers: context.Handlers{ + func(ctx context.Context) { + ctx.StatusCode(http.StatusNotFound) + }, + }, + } +} diff --git a/core/router/handler.go b/core/router/handler.go index bb00eb3a..bd8aed9a 100644 --- a/core/router/handler.go +++ b/core/router/handler.go @@ -33,8 +33,9 @@ type tree struct { } type routerHandler struct { - trees []*tree - hosts bool // true if at least one route contains a Subdomain. + trees []*tree + hosts bool // true if at least one route contains a Subdomain. + fallbackStack *FallbackStack } var _ RequestHandler = &routerHandler{} @@ -82,6 +83,8 @@ func NewDefaultHandler() RequestHandler { type RoutesProvider interface { // api builder GetRoutes() []*Route GetRoute(routeName string) *Route + + FallBackStack() *FallbackStack } func (h *routerHandler) Build(provider RoutesProvider) error { @@ -242,5 +245,5 @@ func (h *routerHandler) HandleRequest(ctx context.Context) { } } - ctx.StatusCode(http.StatusNotFound) + ctx.Do(h.fallbackStack.list()) } diff --git a/core/router/party.go b/core/router/party.go index 6f0e814e..a70c6030 100644 --- a/core/router/party.go +++ b/core/router/party.go @@ -60,6 +60,13 @@ type Party interface { // If the current Party is the root, then it registers the middleware to all child Parties' routes too. Use(middleware ...context.Handler) + // Fallback appends Handler(s) to the current Party's fallback stack. + // Handler(s) is(are) called from Fallback stack when no route found and before sending NotFound status. + // Therefore Handler(s) in Fallback stack could send another thing than NotFound status, + // if `Context.Next()` method is not called. + // Done Handler(s) is(are) not called. + Fallback(middleware ...context.Handler) + // Done appends to the very end, Handler(s) to the current Party's routes and child routes. // The difference from .Use is that this/or these Handler(s) are being always running last. Done(handlers ...context.Handler) diff --git a/mvc/mvc.go b/mvc/mvc.go index f11e02d4..35b21cba 100644 --- a/mvc/mvc.go +++ b/mvc/mvc.go @@ -176,6 +176,13 @@ func (app *Application) Handle(controller interface{}) *Application { return app } +// Fallback is an alias to `app.Router.Fallback(handlers...)` +// +// See `core/router#Party.Fallback` +func (app *Application) Fallback(handlers ...context.Handler) { + app.Router.Fallback(handlers...) +} + // Clone returns a new mvc Application which has the dependencies // of the current mvc Mpplication's dependencies. // From 72b096e156334271b8b54eb8dd6f13b02b2feb4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Meyer?= Date: Wed, 21 Feb 2018 12:27:01 +0300 Subject: [PATCH 2/5] Add fallback handlers Former-commit-id: f7e9bd17076a10e1ed1702780d7ce9e89f00b592 --- .../experimental-handlers/cors/simple/main.go | 8 ++ _examples/routing/fallback-handlers/main.go | 29 +++++ context/application.go | 3 + context/context.go | 8 ++ core/router/api_builder.go | 12 +- core/router/fallback_stack.go | 56 +++++++-- core/router/fallback_stack_test.go | 112 ++++++++++++++++++ core/router/handler.go | 64 +++++++++- core/router/router.go | 5 + core/router/router_test.go | 41 +++++++ 10 files changed, 322 insertions(+), 16 deletions(-) create mode 100644 _examples/routing/fallback-handlers/main.go create mode 100644 core/router/fallback_stack_test.go create mode 100644 core/router/router_test.go diff --git a/_examples/experimental-handlers/cors/simple/main.go b/_examples/experimental-handlers/cors/simple/main.go index 8f9cb1bf..611f664b 100644 --- a/_examples/experimental-handlers/cors/simple/main.go +++ b/_examples/experimental-handlers/cors/simple/main.go @@ -5,6 +5,7 @@ package main import ( "github.com/kataras/iris" + "github.com/kataras/iris/core/router" "github.com/iris-contrib/middleware/cors" ) @@ -14,6 +15,7 @@ func main() { app := iris.New() crs := cors.New(cors.Options{ AllowedOrigins: []string{"*"}, // allows everything, use that to change the hosts. + AllowedMethods: router.AllMethods[:], AllowCredentials: true, }) @@ -29,6 +31,12 @@ func main() { v1.Post("/send", func(ctx iris.Context) { ctx.WriteString("sent") }) + v1.Put("/send", func(ctx iris.Context) { + ctx.WriteString("updated") + }) + v1.Delete("/send", func(ctx iris.Context) { + ctx.WriteString("deleted") + }) } // or use that to wrap the entire router diff --git a/_examples/routing/fallback-handlers/main.go b/_examples/routing/fallback-handlers/main.go new file mode 100644 index 00000000..3c1e8e78 --- /dev/null +++ b/_examples/routing/fallback-handlers/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "github.com/kataras/iris" +) + +func main() { + app := iris.New() + + // this works as expected now, + // will handle *all* expect DELETE requests, even if there is no routes + app.Get("/action/{p}", h) + + app.Run(iris.Addr(":8080"), ctx.Method(), ctx.Path(), iris.WithoutServerError(iris.ErrServerClosed)) +} + +func h(ctx iris.Context) { + ctx.Writef("[%s] %s : Parameter = `%s`", ctx.Params().Get("p")) +} + +func fallbackHandler(ctx iris.Context) { + if ctx.Method() == "DELETE" { + ctx.Next() + + return + } + + ctx.Writef("[%s] %s : From fallback handler", ctx.Method(), ctx.Path()) +} diff --git a/context/application.go b/context/application.go index 90738ce7..6ac8bd1f 100644 --- a/context/application.go +++ b/context/application.go @@ -48,4 +48,7 @@ type Application interface { // If a handler is not already registered, // then it creates & registers a new trivial handler on the-fly. FireErrorCode(ctx Context) + + // RouteExists checks if a route exists + RouteExists(method string, path string, ctx Context) bool } diff --git a/context/context.go b/context/context.go index dc3ecf80..1143aa2a 100644 --- a/context/context.go +++ b/context/context.go @@ -905,6 +905,9 @@ type Context interface { // It's for extreme use cases, 99% of the times will never be useful for you. Exec(method string, path string) + // RouteExists checks if a route exists + RouteExists(method string, path string) bool + // Application returns the iris app instance which belongs to this context. // Worth to notice that this function returns an interface // of the Application, which contains methods that are safe @@ -3130,6 +3133,11 @@ func (ctx *context) Exec(method string, path string) { } } +// RouteExists checks if a route exists +func (ctx *context) RouteExists(method string, path string) bool { + return ctx.Application().RouteExists(method, path, ctx) +} + // Application returns the iris app instance which belongs to this context. // Worth to notice that this function returns an interface // of the Application, which contains methods that are safe diff --git a/core/router/api_builder.go b/core/router/api_builder.go index e0cfc4d7..a300760c 100644 --- a/core/router/api_builder.go +++ b/core/router/api_builder.go @@ -273,7 +273,7 @@ func (api *APIBuilder) Party(relativePath string, handlers ...context.Handler) P // per-party/children middleware: middleware, doneHandlers: api.doneHandlers, - fallbackStack: api.fallbackStack, + fallbackStack: api.fallbackStack.Fork(), relativePath: fullpath, } } @@ -426,13 +426,19 @@ func (api *APIBuilder) DoneGlobal(handlers ...context.Handler) { api.doneGlobalHandlers = append(api.doneGlobalHandlers, handlers...) } -// Fallback appends Handler(s) to the current Party's fallback stack. +// Fallback appends Handler(s) to the current fallback stack. // Handler(s) is(are) called from Fallback stack when no route found and before sending NotFound status. // Therefore Handler(s) in Fallback stack could send another thing than NotFound status, // if `Context.Next()` method is not called. // Done & DoneGlobal Handlers are not called. func (api *APIBuilder) Fallback(middleware ...context.Handler) { - api.fallbackStack.add(middleware) + api.fallbackStack.Add(middleware) +} + +// FallBackStack returns Fallback stack, this is implementation of interface RoutesProvider +// that is used in Router building by the RequestHandler. +func (api *APIBuilder) GetFallBackStack() *FallbackStack { + return api.fallbackStack } // Reset removes all the begin and done handlers that may derived from the parent party via `Use` & `Done`, diff --git a/core/router/fallback_stack.go b/core/router/fallback_stack.go index 499e0896..1b8531f8 100644 --- a/core/router/fallback_stack.go +++ b/core/router/fallback_stack.go @@ -2,37 +2,71 @@ package router import ( "net/http" - "sync" "github.com/kataras/iris/context" ) +// FallbackStack is a stack (with LIFO calling order) for fallback handlers +// A fallback handler(s) is(are) called from Fallback stack +// when no route found and before sending NotFound status. +// Therefore Handler(s) in Fallback stack could send another thing than NotFound status, +// if `Context.Next()` method is not called. +// Done & DoneGlobal Handlers are not called. type FallbackStack struct { + parent *FallbackStack handlers context.Handlers - m sync.Mutex } -func (stk *FallbackStack) add(h context.Handlers) { - stk.m.Lock() - defer stk.m.Unlock() +// _size is a terminal recursive method for computing size the stack +func (stk *FallbackStack) _size(i int) int { + res := i + len(stk.handlers) + if stk.parent == nil { + return res + } + + return stk.parent._size(res) +} + +// populate is a recursive method for concatenating handlers to `list` parameter +func (stk *FallbackStack) populate(list context.Handlers) { + n := copy(list, stk.handlers) + + if stk.parent != nil { + stk.parent.populate(list[n:]) + } +} + +// Size gives the size of the full stack hierarchy +func (stk *FallbackStack) Size() int { + return stk._size(0) +} + +// Add appends handlers to the beginning of the stack to have a LIFO calling order +func (stk *FallbackStack) Add(h context.Handlers) { stk.handlers = append(stk.handlers, h...) copy(stk.handlers[len(h):], stk.handlers) copy(stk.handlers, h) } -func (stk *FallbackStack) list() context.Handlers { - res := make(context.Handlers, len(stk.handlers)) +// Fork make a new stack from this stack, and so create a stack child (leaf from a tree of stacks) +func (stk *FallbackStack) Fork() *FallbackStack { + return &FallbackStack{ + parent: stk, + } +} - stk.m.Lock() - defer stk.m.Unlock() - - copy(res, stk.handlers) +// List concatenate all handlers in stack hierarchy +func (stk *FallbackStack) List() context.Handlers { + res := make(context.Handlers, stk.Size()) + stk.populate(res) return res } +// NewFallbackStack create a new Fallback stack with as first entry +// a handler which send NotFound status (the default) func NewFallbackStack() *FallbackStack { return &FallbackStack{ handlers: context.Handlers{ diff --git a/core/router/fallback_stack_test.go b/core/router/fallback_stack_test.go new file mode 100644 index 00000000..1499cd96 --- /dev/null +++ b/core/router/fallback_stack_test.go @@ -0,0 +1,112 @@ +package router_test + +import ( + "testing" + + "github.com/kataras/iris" + "github.com/kataras/iris/context" + "github.com/kataras/iris/core/router" + "github.com/kataras/iris/httptest" +) + +func TestFallbackStackAdd(t *testing.T) { + l := make([]string, 0) + + stk := &router.FallbackStack{} + stk.Add(context.Handlers{ + func(context.Context) { + l = append(l, "POS1") + }, + }) + + stk.Add(context.Handlers{ + func(context.Context) { + l = append(l, "POS2") + }, + }) + + if stk.Size() != 2 { + t.Fatalf("Bad size (%d != 2)", stk.Size()) + } + + for _, h := range stk.List() { + h(nil) + } + + if (l[0] != "POS2") || (l[1] != "POS1") { + t.Fatal("Bad positions: ", l) + } +} + +func TestFallbackStackFork(t *testing.T) { + l := make([]string, 0) + + stk := &router.FallbackStack{} + + stk.Add(context.Handlers{ + func(context.Context) { + l = append(l, "POS1") + }, + }) + + stk.Add(context.Handlers{ + func(context.Context) { + l = append(l, "POS2") + }, + }) + + stk = stk.Fork() + + stk.Add(context.Handlers{ + func(context.Context) { + l = append(l, "POS3") + }, + }) + + stk.Add(context.Handlers{ + func(context.Context) { + l = append(l, "POS4") + }, + }) + + if stk.Size() != 4 { + t.Fatalf("Bad size (%d != 4)", stk.Size()) + } + + for _, h := range stk.List() { + h(nil) + } + + if (l[0] != "POS4") || (l[1] != "POS3") || (l[2] != "POS2") || (l[3] != "POS1") { + t.Fatal("Bad positions: ", l) + } +} + +func TestFallbackStackCall(t *testing.T) { + // build the api + app := iris.New() + + // setup an existing routes + app.Handle("GET", "/route", func(ctx context.Context) { + ctx.WriteString("ROUTED") + }) + + // setup fallback handler + app.Fallback(func(ctx context.Context) { + if ctx.Method() != "GET" { + ctx.Next() + + return + } + + ctx.WriteString("FALLBACK") + }) + + // run the tests + e := httptest.New(t, app, httptest.Debug(false)) + + e.Request("GET", "/route").Expect().Status(iris.StatusOK).Body().Equal("ROUTED") + e.Request("POST", "/route").Expect().Status(iris.StatusNotFound) + e.Request("POST", "/noroute").Expect().Status(iris.StatusNotFound) + e.Request("GET", "/noroute").Expect().Status(iris.StatusOK).Body().Equal("FALLBACK") +} diff --git a/core/router/handler.go b/core/router/handler.go index bd8aed9a..ce924493 100644 --- a/core/router/handler.go +++ b/core/router/handler.go @@ -22,6 +22,8 @@ type RequestHandler interface { HandleRequest(context.Context) // Build should builds the handler, it's being called on router's BuildRouter. Build(provider RoutesProvider) error + // RouteExists checks if a route exists + RouteExists(method, path string, ctx context.Context) bool } type tree struct { @@ -84,12 +86,13 @@ type RoutesProvider interface { // api builder GetRoutes() []*Route GetRoute(routeName string) *Route - FallBackStack() *FallbackStack + GetFallBackStack() *FallbackStack } func (h *routerHandler) Build(provider RoutesProvider) error { registeredRoutes := provider.GetRoutes() h.trees = h.trees[0:0] // reset, inneed when rebuilding. + h.fallbackStack = provider.GetFallBackStack() // sort, subdomains goes first. sort.Slice(registeredRoutes, func(i, j int) bool { @@ -245,5 +248,62 @@ func (h *routerHandler) HandleRequest(ctx context.Context) { } } - ctx.Do(h.fallbackStack.list()) + if h.fallbackStack == nil { + ctx.StatusCode(http.StatusNotFound) + } else { + ctx.Do(h.fallbackStack.List()) + } +} + +// RouteExists checks if a route exists +func (h *routerHandler) RouteExists(method, path string, ctx context.Context) bool { + for i := range h.trees { + t := h.trees[i] + if method != t.Method { + continue + } + + if h.hosts && t.Subdomain != "" { + requestHost := ctx.Host() + if netutil.IsLoopbackSubdomain(requestHost) { + // this fixes a bug when listening on + // 127.0.0.1:8080 for example + // and have a wildcard subdomain and a route registered to root domain. + continue // it's not a subdomain, it's something like 127.0.0.1 probably + } + // it's a dynamic wildcard subdomain, we have just to check if ctx.subdomain is not empty + if t.Subdomain == SubdomainWildcardIndicator { + // mydomain.com -> invalid + // localhost -> invalid + // sub.mydomain.com -> valid + // sub.localhost -> valid + serverHost := ctx.Application().ConfigurationReadOnly().GetVHost() + if serverHost == requestHost { + continue // it's not a subdomain, it's a full domain (with .com...) + } + + dotIdx := strings.IndexByte(requestHost, '.') + slashIdx := strings.IndexByte(requestHost, '/') + if dotIdx > 0 && (slashIdx == -1 || slashIdx > dotIdx) { + // if "." was found anywhere but not at the first path segment (host). + } else { + continue + } + // continue to that, any subdomain is valid. + } else if !strings.HasPrefix(requestHost, t.Subdomain) { // t.Subdomain contains the dot. + continue + } + } + + _, handlers := t.Nodes.Find(path, ctx.Params()) + if len(handlers) > 0 { + // found + return true + } + + // not found or method not allowed. + break + } + + return false } diff --git a/core/router/router.go b/core/router/router.go index 9b81d2ea..891813e1 100644 --- a/core/router/router.go +++ b/core/router/router.go @@ -147,6 +147,11 @@ func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) { router.mainHandler(w, r) } +// RouteExists checks if a route exists +func (router *Router) RouteExists(method, path string, ctx context.Context) bool { + return router.requestHandler.RouteExists(method, path, ctx) +} + type wrapper struct { router http.HandlerFunc // http.HandlerFunc to catch the CURRENT state of its .ServeHTTP on case of future change. wrapperFunc func(http.ResponseWriter, *http.Request, http.HandlerFunc) diff --git a/core/router/router_test.go b/core/router/router_test.go new file mode 100644 index 00000000..ba41a714 --- /dev/null +++ b/core/router/router_test.go @@ -0,0 +1,41 @@ +package router_test + +import ( + "testing" + + "github.com/kataras/iris" + "github.com/kataras/iris/context" + "github.com/kataras/iris/httptest" +) + +func TestRouteExists(t *testing.T) { + // build the api + app := iris.New() + emptyHandler := func(context.Context) {} + + // setup the tested routes + app.Handle("GET", "/route-exists", emptyHandler) + app.Handle("POST", "/route-with-param/{param}", emptyHandler) + + // check RouteExists + app.Handle("GET", "/route-test", func(ctx context.Context) { + if ctx.RouteExists("GET", "/route-not-exists") { + t.Error("Route with path should not exists") + } + + if ctx.RouteExists("POST", "/route-exists") { + t.Error("Route with method should not exists") + } + + if !ctx.RouteExists("GET", "/route-exists") { + t.Error("Route 1 should exists") + } + + if !ctx.RouteExists("POST", "/route-with-param/a-param") { + t.Error("Route 2 should exists") + } + }) + + // run the tests + httptest.New(t, app, httptest.Debug(false)).Request("GET", "/route-test").Expect().Status(iris.StatusOK) +} From 643358d7cb509a7719343df62021d4558703ede3 Mon Sep 17 00:00:00 2001 From: ZaniaDevelopper Date: Wed, 21 Feb 2018 14:22:17 +0300 Subject: [PATCH 3/5] Modification - Add configurator for Party - Modification for CORS middleware example Former-commit-id: f01c01d4eac41666a92890461851909a6ade018b --- _examples/experimental-handlers/cors/simple/main.go | 4 ++-- core/router/api_builder.go | 8 ++++++++ core/router/party.go | 7 +++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/_examples/experimental-handlers/cors/simple/main.go b/_examples/experimental-handlers/cors/simple/main.go index 611f664b..a4557b20 100644 --- a/_examples/experimental-handlers/cors/simple/main.go +++ b/_examples/experimental-handlers/cors/simple/main.go @@ -13,14 +13,14 @@ import ( func main() { app := iris.New() - crs := cors.New(cors.Options{ + crs := cors.NewPartyMiddleware(cors.Options{ AllowedOrigins: []string{"*"}, // allows everything, use that to change the hosts. AllowedMethods: router.AllMethods[:], AllowCredentials: true, }) v1 := app.Party("/api/v1") - v1.Use(crs) + v1.ConfigureParty(crs) { v1.Get("/home", func(ctx iris.Context) { ctx.WriteString("Hello from /home") diff --git a/core/router/api_builder.go b/core/router/api_builder.go index a300760c..ab3d3f2c 100644 --- a/core/router/api_builder.go +++ b/core/router/api_builder.go @@ -114,6 +114,14 @@ func NewAPIBuilder() *APIBuilder { return api } +// ConfigureParty configures this party like `iris.Application#Configure` +// That allows middlewares focused on the Party like CORS middleware +func (api *APIBuilder) ConfigureParty(conf ...PartyConfigurator) { + for _, h := range conf { + h(api) + } +} + // GetRelPath returns the current party's relative path. // i.e: // if r := app.Party("/users"), then the `r.GetRelPath()` is the "/users". diff --git a/core/router/party.go b/core/router/party.go index a70c6030..8a91e727 100644 --- a/core/router/party.go +++ b/core/router/party.go @@ -9,11 +9,18 @@ import ( // Party is here to separate the concept of // api builder and the sub api builder. +// PartyConfigurator is handler for configuring a party (it works with iris.Application) +type PartyConfigurator func(party Party) + // Party is just a group joiner of routes which have the same prefix and share same middleware(s) also. // Party could also be named as 'Join' or 'Node' or 'Group' , Party chosen because it is fun. // // Look the "APIBuilder" for its implementation. type Party interface { + // ConfigureParty configures this party like `iris.Application#Configure` + // That allows middlewares focused on the Party like CORS middleware + ConfigureParty(...PartyConfigurator) + // GetRelPath returns the current party's relative path. // i.e: // if r := app.Party("/users"), then the `r.GetRelPath()` is the "/users". From 7a29519c5aa6eeb90660088952417da3e983afbd Mon Sep 17 00:00:00 2001 From: ZaniaDevelopper Date: Wed, 21 Feb 2018 14:48:09 +0300 Subject: [PATCH 4/5] Fixes bad copy/paste Former-commit-id: 437b60bc6b37d8a755198fb97809c61b9c18004e --- _examples/routing/fallback-handlers/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_examples/routing/fallback-handlers/main.go b/_examples/routing/fallback-handlers/main.go index 3c1e8e78..66308ae4 100644 --- a/_examples/routing/fallback-handlers/main.go +++ b/_examples/routing/fallback-handlers/main.go @@ -11,11 +11,11 @@ func main() { // will handle *all* expect DELETE requests, even if there is no routes app.Get("/action/{p}", h) - app.Run(iris.Addr(":8080"), ctx.Method(), ctx.Path(), iris.WithoutServerError(iris.ErrServerClosed)) + app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) } func h(ctx iris.Context) { - ctx.Writef("[%s] %s : Parameter = `%s`", ctx.Params().Get("p")) + ctx.Writef("[%s] %s : Parameter = `%s`", ctx.Method(), ctx.Path(), ctx.Params().Get("p")) } func fallbackHandler(ctx iris.Context) { From 1196680004fefaefa520f9f3429f3d45da8a4fe5 Mon Sep 17 00:00:00 2001 From: ZaniaDevelopper Date: Wed, 21 Feb 2018 15:19:09 +0300 Subject: [PATCH 5/5] Add comment in example Former-commit-id: 2b9d7a569ed4c5d78cd5dd49865df1cf381619fc --- _examples/experimental-handlers/cors/simple/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_examples/experimental-handlers/cors/simple/main.go b/_examples/experimental-handlers/cors/simple/main.go index a4557b20..94593b08 100644 --- a/_examples/experimental-handlers/cors/simple/main.go +++ b/_examples/experimental-handlers/cors/simple/main.go @@ -13,6 +13,8 @@ import ( func main() { app := iris.New() + + // `crs := cors.NewAllowAllPartyMiddleware()`, or: crs := cors.NewPartyMiddleware(cors.Options{ AllowedOrigins: []string{"*"}, // allows everything, use that to change the hosts. AllowedMethods: router.AllMethods[:],