mirror of
https://github.com/kataras/iris.git
synced 2025-03-15 08:06:27 +01:00
add route-handlers-execution-rules example
Former-commit-id: 95e3dfad33b98d20b761ea1d06dee8df91c3632d
This commit is contained in:
parent
7e98555e6b
commit
6557dcf6c5
|
@ -43,6 +43,7 @@
|
||||||
* Middleware
|
* Middleware
|
||||||
* [Per Route](routing/writing-a-middleware/per-route/main.go)
|
* [Per Route](routing/writing-a-middleware/per-route/main.go)
|
||||||
* [Globally](routing/writing-a-middleware/globally/main.go)
|
* [Globally](routing/writing-a-middleware/globally/main.go)
|
||||||
|
* [Handlers Execution Rule](routing/route-handlers-execution-rules/main.go)
|
||||||
* [Route Register Rule](routing/route-register-rule/main.go)
|
* [Route Register Rule](routing/route-register-rule/main.go)
|
||||||
* Convert net/http Handlers
|
* Convert net/http Handlers
|
||||||
* [From func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)](convert-handlers/negroni-like/main.go)
|
* [From func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)](convert-handlers/negroni-like/main.go)
|
||||||
|
|
|
@ -1,26 +1,7 @@
|
||||||
/*Package main is a simple example of the behavior change of the execution flow of the handlers,
|
/*Package main shows how to add done handlers in an MVC application without
|
||||||
normally we need the `ctx.Next()` to call the next handler in a route's handler chain,
|
the necessity of `ctx.Next()` inside the controller's methods.
|
||||||
but with the new `ExecutionRules` we can change this default behavior.
|
|
||||||
Please read below before continue.
|
|
||||||
|
|
||||||
The `Party#SetExecutionRules` alters the execution flow of the route handlers outside of the handlers themselves.
|
When we want the `Done` handlers of that specific mvc app's `Party`
|
||||||
|
|
||||||
For example, if for some reason the desired result is the (done or all) handlers to be executed no matter what
|
|
||||||
even if no `ctx.Next()` is called in the previous handlers, including the begin(`Use`),
|
|
||||||
the main(`Handle`) and the done(`Done`) handlers themselves, then:
|
|
||||||
Party#SetExecutionRules(iris.ExecutionRules {
|
|
||||||
Begin: iris.ExecutionOptions{Force: true},
|
|
||||||
Main: iris.ExecutionOptions{Force: true},
|
|
||||||
Done: iris.ExecutionOptions{Force: true},
|
|
||||||
})
|
|
||||||
|
|
||||||
Note that if `true` then the only remained way to "break" the handler chain is by `ctx.StopExecution()` now that `ctx.Next()` does not matter.
|
|
||||||
|
|
||||||
These rules are per-party, so if a `Party` creates a child one then the same rules will be applied to that as well.
|
|
||||||
Reset of these rules (before `Party#Handle`) can be done with `Party#SetExecutionRules(iris.ExecutionRules{})`.
|
|
||||||
|
|
||||||
The most common scenario for its use can be found inside Iris MVC Applications;
|
|
||||||
when we want the `Done` handlers of that specific mvc app's `Party`
|
|
||||||
to be executed but we don't want to add `ctx.Next()` on the `exampleController#EndRequest`*/
|
to be executed but we don't want to add `ctx.Next()` on the `exampleController#EndRequest`*/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
@ -33,23 +14,17 @@ func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
app.Get("/", func(ctx iris.Context) { ctx.Redirect("/example") })
|
app.Get("/", func(ctx iris.Context) { ctx.Redirect("/example") })
|
||||||
|
|
||||||
// example := app.Party("/example")
|
exampleRouter := app.Party("/example")
|
||||||
// example.SetExecutionRules && mvc.New(example) or...
|
{
|
||||||
m := mvc.New(app.Party("/example"))
|
exampleRouter.SetExecutionRules(iris.ExecutionRules{
|
||||||
|
Done: iris.ExecutionOptions{Force: true},
|
||||||
|
})
|
||||||
|
|
||||||
// IMPORTANT
|
exampleRouter.Done(doneHandler)
|
||||||
// All options can be filled with Force:true, they all play nice together.
|
|
||||||
m.Router.SetExecutionRules(iris.ExecutionRules{
|
|
||||||
// Begin: <- from `Use[all]` to `Handle[last]` future route handlers, execute all, execute all even if `ctx.Next()` is missing.
|
|
||||||
// Main: <- all `Handle` future route handlers, execute all >> >>.
|
|
||||||
Done: iris.ExecutionOptions{Force: true}, // <- from `Handle[last]` to `Done[all]` future route handlers, execute all >> >>.
|
|
||||||
})
|
|
||||||
m.Router.Done(doneHandler)
|
|
||||||
// m.Router.Done(...)
|
|
||||||
// ...
|
|
||||||
//
|
|
||||||
|
|
||||||
m.Handle(&exampleController{})
|
m := mvc.New(exampleRouter)
|
||||||
|
m.Handle(&exampleController{})
|
||||||
|
}
|
||||||
|
|
||||||
app.Listen(":8080")
|
app.Listen(":8080")
|
||||||
}
|
}
|
||||||
|
@ -64,7 +39,8 @@ func (c *exampleController) Get() string {
|
||||||
return "From Main Handler"
|
return "From Main Handler"
|
||||||
// Note that here we don't binding the `Context`, and we don't call its `Next()`
|
// Note that here we don't binding the `Context`, and we don't call its `Next()`
|
||||||
// function in order to call the `doneHandler`,
|
// function in order to call the `doneHandler`,
|
||||||
// this is done automatically for us because we changed the execution rules with the `SetExecutionRules`.
|
// this is done automatically for us because we changed the execution rules with the
|
||||||
|
// `SetExecutionRules`.
|
||||||
//
|
//
|
||||||
// Therefore the final output is:
|
// Therefore the final output is:
|
||||||
// From Main Handler
|
// From Main Handler
|
||||||
|
|
61
_examples/routing/route-handlers-execution-rules/main.go
Normal file
61
_examples/routing/route-handlers-execution-rules/main.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*Package main is a simple example of the behavior change of the execution flow of the handlers,
|
||||||
|
normally we need the `ctx.Next()` to call the next handler in a route's handler chain,
|
||||||
|
but with the `ExecutionRules` we can change this default behavior.
|
||||||
|
Please read below before continue.
|
||||||
|
|
||||||
|
The `Party#SetExecutionRules` alters the execution flow of the route handlers.
|
||||||
|
|
||||||
|
For example, if for some reason the desired result is the (done or all) handlers
|
||||||
|
to be executed no matter what, even if no `ctx.Next()` is called in the previous handlers:
|
||||||
|
|
||||||
|
app.SetExecutionRules(iris.ExecutionRules {
|
||||||
|
Begin: iris.ExecutionOptions{Force: true}, # begin handlers(.Use)
|
||||||
|
Main: iris.ExecutionOptions{Force: true}, # main handler (.Handle/Get...)
|
||||||
|
Done: iris.ExecutionOptions{Force: true}, # done handlers (.Done)
|
||||||
|
})
|
||||||
|
|
||||||
|
Note that if `true` then the only remained way to "break" the handler chain
|
||||||
|
is by calling the `ctx.StopExecution()` (now that `ctx.Next()` doesn't even matter).
|
||||||
|
|
||||||
|
These rules are per-party, so if a `Party` creates a child one then
|
||||||
|
the same rules will be applied to that as well.
|
||||||
|
|
||||||
|
Reset of these rules to their defaults (before `Party#Handle`) can be done
|
||||||
|
with `Party#SetExecutionRules(iris.ExecutionRules{})`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/kataras/iris/v12"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := iris.New()
|
||||||
|
|
||||||
|
app.SetExecutionRules(iris.ExecutionRules{
|
||||||
|
// * From `Use[all]` to `Handle[last]` future route handlers,
|
||||||
|
// execute all (even if `ctx.Next()` is missing):
|
||||||
|
// Begin: true,
|
||||||
|
//
|
||||||
|
// * All `Handle` future route handlers, execute all:
|
||||||
|
// Main: true,
|
||||||
|
//
|
||||||
|
// * From `Handle[last]` to `Done[last]` future route handlers, execute all:
|
||||||
|
Done: iris.ExecutionOptions{Force: true},
|
||||||
|
})
|
||||||
|
app.Done(doneHandler)
|
||||||
|
|
||||||
|
app.Get("/", mainHandler)
|
||||||
|
|
||||||
|
// http://localhost:8080
|
||||||
|
app.Listen(":8080")
|
||||||
|
}
|
||||||
|
|
||||||
|
func mainHandler(ctx iris.Context) {
|
||||||
|
ctx.WriteString("From Main Handler\n")
|
||||||
|
// ctx.Next() is not required now that we have declared
|
||||||
|
// Done: iris.ExecutionOptions{Force: true}.
|
||||||
|
}
|
||||||
|
|
||||||
|
func doneHandler(ctx iris.Context) {
|
||||||
|
ctx.WriteString("From Done Handler\n")
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ func main() {
|
||||||
// are applied to existing routes and future routes.
|
// are applied to existing routes and future routes.
|
||||||
//
|
//
|
||||||
// Remember: the `Use` and `Done` are applied to the current party's and its children,
|
// Remember: the `Use` and `Done` are applied to the current party's and its children,
|
||||||
// so if we used the `app.Use/Don`e before the routes registration
|
// so if we used the `app.Use/Done` before the routes registration
|
||||||
// it would work like UseGlobal/DoneGlobal in this case, because the `app` is the root party.
|
// it would work like UseGlobal/DoneGlobal in this case, because the `app` is the root party.
|
||||||
//
|
//
|
||||||
// See `app.Party/PartyFunc` for more.
|
// See `app.Party/PartyFunc` for more.
|
||||||
|
|
|
@ -1513,7 +1513,7 @@ func DefaultNext(ctx Context) {
|
||||||
// it should be used inside a middleware.
|
// it should be used inside a middleware.
|
||||||
//
|
//
|
||||||
// Note: Custom context should override this method in order to be able to pass its own context.Context implementation.
|
// Note: Custom context should override this method in order to be able to pass its own context.Context implementation.
|
||||||
func (ctx *context) Next() { // or context.Next(ctx)
|
func (ctx *context) Next() {
|
||||||
Next(ctx)
|
Next(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user