Former-commit-id: 592e9cddf3511fc08e87f19ad39fdaac479b453f
This commit is contained in:
Frédéric Meyer 2018-02-21 08:18:53 +03:00
parent c0e0886cb9
commit 66209cae4f
6 changed files with 81 additions and 7 deletions

View File

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

View File

@ -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`.
//

View File

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

View File

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

View File

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

View File

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