mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 02:31:04 +01:00
add 'Configuration.PathIntelligence' and 'OnErrorCode' and 'OnAnyErrorCode' on APIContainer
Former-commit-id: bc3d0232106622063205f326bfa4ed3aa84179de
This commit is contained in:
parent
21a013569f
commit
1e20996330
|
@ -371,6 +371,8 @@ Other Improvements:
|
|||
|
||||
![DBUG routes](https://iris-go.com/images/v12.2.0-dbug2.png?v=0)
|
||||
|
||||
- `Configuration.EnablePathIntelligence | iris.WithPathIntelligence` to enable path intelligence automatic path redirection on the most closest path (if any), [example]((https://github.com/kataras/iris/blob/master/_examples/routing/intelligence/main.go)
|
||||
|
||||
- Enhanced cookie security and management through new `Context.AddCookieOptions` method and new cookie options (look on New Package-level functions section below), [securecookie](https://github.com/kataras/iris/tree/master/_examples/cookies/securecookie) example has been updated.
|
||||
- `Context.RemoveCookie` removes also the Request's specific cookie of the same request lifecycle when `iris.CookieAllowReclaim` is set to cookie options, [example](https://github.com/kataras/iris/tree/master/_examples/cookies/options).
|
||||
|
||||
|
@ -494,7 +496,7 @@ Fix [[BUG]Session works incorrectly when meets the multi-level TLDs](https://git
|
|||
|
||||
# Mo, 16 December 2019 | v12.1.1
|
||||
|
||||
Add [Context.FindClosest(n int) []string](https://github.com/kataras/iris/blob/master/_examples/routing/not-found-suggests/main.go#L22)
|
||||
Add [Context.FindClosest(n int) []string](https://github.com/kataras/iris/blob/master/_examples/routing/intelligence/manual/main.go#L22)
|
||||
|
||||
```go
|
||||
app := iris.New()
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
* [Overview](routing/overview/main.go)
|
||||
* [Basic](routing/basic/main.go)
|
||||
* [Custom HTTP Errors](routing/http-errors/main.go)
|
||||
* [Not Found - Suggest Closest Paths](routing/not-found-suggests/main.go)
|
||||
* [Not Found - Intelligence](routing/intelligence/main.go)
|
||||
* [Not Found - Suggest Closest Paths](routing/intelligence/manual/main.go)
|
||||
* [Dynamic Path](routing/dynamic-path/main.go)
|
||||
* [Root Wildcard](routing/dynamic-path/root-wildcard/main.go)
|
||||
* [Implement a Parameter Type](routing/macros/main.go)
|
||||
|
|
24
_examples/routing/intelligence/main.go
Normal file
24
_examples/routing/intelligence/main.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package main
|
||||
|
||||
import "github.com/kataras/iris/v12"
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Get("/home", handler)
|
||||
app.Get("/contact", handler)
|
||||
app.Get("/contract", handler)
|
||||
|
||||
// http://localhost:8080/home
|
||||
// http://localhost:8080/hom
|
||||
//
|
||||
// http://localhost:8080/contact
|
||||
// http://localhost:8080/cont
|
||||
//
|
||||
// http://localhost:8080/contract
|
||||
// http://localhost:8080/contr
|
||||
app.Listen(":8080", iris.WithPathIntelligence)
|
||||
}
|
||||
|
||||
func handler(ctx iris.Context) {
|
||||
ctx.Writef("Path: %s", ctx.Path())
|
||||
}
|
|
@ -240,6 +240,13 @@ var WithoutPathCorrection = func(app *Application) {
|
|||
app.config.DisablePathCorrection = true
|
||||
}
|
||||
|
||||
// WithPathIntelligence enables the EnablePathIntelligence setting.
|
||||
//
|
||||
// See `Configuration`.
|
||||
var WithPathIntelligence = func(app *Application) {
|
||||
app.config.EnablePathIntelligence = true
|
||||
}
|
||||
|
||||
// WithoutPathCorrectionRedirection disables the PathCorrectionRedirection setting.
|
||||
//
|
||||
// See `Configuration`.
|
||||
|
@ -781,14 +788,21 @@ type Configuration struct {
|
|||
//
|
||||
// Defaults to false.
|
||||
DisablePathCorrection bool `json:"disablePathCorrection,omitempty" yaml:"DisablePathCorrection" toml:"DisablePathCorrection"`
|
||||
|
||||
// DisablePathCorrectionRedirection works whenever configuration.DisablePathCorrection is set to false
|
||||
// and if DisablePathCorrectionRedirection set to true then it will fire the handler of the matching route without
|
||||
// the trailing slash ("/") instead of send a redirection status.
|
||||
//
|
||||
// Defaults to false.
|
||||
DisablePathCorrectionRedirection bool `json:"disablePathCorrectionRedirection,omitempty" yaml:"DisablePathCorrectionRedirection" toml:"DisablePathCorrectionRedirection"`
|
||||
|
||||
// EnablePathIntelligence if set to true,
|
||||
// the router will redirect HTTP "GET" not found pages to the most closest one path(if any). For example
|
||||
// you register a route at "/contact" path -
|
||||
// a client tries to reach it by "/cont", the path will be automatic fixed
|
||||
// and the client will be redirected to the "/contact" path
|
||||
// instead of getting a 404 not found response back.
|
||||
//
|
||||
// Defaults to false.
|
||||
EnablePathIntelligence bool `json:"enablePathIntelligence,omitempty" yaml:"EnablePathIntelligence" toml:"EnablePathIntelligence"`
|
||||
// EnablePathEscape when is true then its escapes the path and the named parameters (if any).
|
||||
// When do you need to Disable(false) it:
|
||||
// accepts parameters with slash '/'
|
||||
|
@ -799,23 +813,21 @@ type Configuration struct {
|
|||
//
|
||||
// Defaults to false.
|
||||
EnablePathEscape bool `json:"enablePathEscape,omitempty" yaml:"EnablePathEscape" toml:"EnablePathEscape"`
|
||||
|
||||
// ForceLowercaseRouting if enabled, converts all registered routes paths to lowercase
|
||||
// and it does lowercase the request path too for matching.
|
||||
//
|
||||
// Defaults to false.
|
||||
ForceLowercaseRouting bool `json:"forceLowercaseRouting,omitempty" yaml:"ForceLowercaseRouting" toml:"ForceLowercaseRouting"`
|
||||
// FireMethodNotAllowed if it's true router checks for StatusMethodNotAllowed(405) and
|
||||
// fires the 405 error instead of 404
|
||||
// Defaults to false.
|
||||
FireMethodNotAllowed bool `json:"fireMethodNotAllowed,omitempty" yaml:"FireMethodNotAllowed" toml:"FireMethodNotAllowed"`
|
||||
|
||||
// EnableOptimization when this field is true
|
||||
// then the application tries to optimize for the best performance where is possible.
|
||||
//
|
||||
// Defaults to false.
|
||||
EnableOptimizations bool `json:"enableOptimizations,omitempty" yaml:"EnableOptimizations" toml:"EnableOptimizations"`
|
||||
// FireMethodNotAllowed if it's true router checks for StatusMethodNotAllowed(405) and
|
||||
// fires the 405 error instead of 404
|
||||
// Defaults to false.
|
||||
FireMethodNotAllowed bool `json:"fireMethodNotAllowed,omitempty" yaml:"FireMethodNotAllowed" toml:"FireMethodNotAllowed"`
|
||||
|
||||
// DisableBodyConsumptionOnUnmarshal manages the reading behavior of the context's body readers/binders.
|
||||
// If set to true then it
|
||||
// disables the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`.
|
||||
|
@ -962,35 +974,40 @@ func (c Configuration) GetDisablePathCorrection() bool {
|
|||
return c.DisablePathCorrection
|
||||
}
|
||||
|
||||
// GetDisablePathCorrectionRedirection returns the Configuration#DisablePathCorrectionRedirection field.
|
||||
// GetDisablePathCorrectionRedirection returns the Configuration.DisablePathCorrectionRedirection field.
|
||||
// If DisablePathCorrectionRedirection set to true then it will fire the handler of the matching route without
|
||||
// the last slash ("/") instead of send a redirection status.
|
||||
func (c Configuration) GetDisablePathCorrectionRedirection() bool {
|
||||
return c.DisablePathCorrectionRedirection
|
||||
}
|
||||
|
||||
// GetEnablePathEscape is the Configuration#EnablePathEscape,
|
||||
// GetEnablePathIntelligence returns the Configuration.EnablePathIntelligence field.
|
||||
func (c Configuration) GetEnablePathIntelligence() bool {
|
||||
return c.EnablePathIntelligence
|
||||
}
|
||||
|
||||
// GetEnablePathEscape is the Configuration.EnablePathEscape,
|
||||
// returns true when its escapes the path, the named parameters (if any).
|
||||
func (c Configuration) GetEnablePathEscape() bool {
|
||||
return c.EnablePathEscape
|
||||
}
|
||||
|
||||
// GetForceLowercaseRouting returns the value of the `ForceLowercaseRouting` setting.
|
||||
// GetForceLowercaseRouting returns the value of the Configuration.ForceLowercaseRouting setting.
|
||||
func (c Configuration) GetForceLowercaseRouting() bool {
|
||||
return c.ForceLowercaseRouting
|
||||
}
|
||||
|
||||
// GetFireMethodNotAllowed returns the Configuration.FireMethodNotAllowed.
|
||||
func (c Configuration) GetFireMethodNotAllowed() bool {
|
||||
return c.FireMethodNotAllowed
|
||||
}
|
||||
|
||||
// GetEnableOptimizations returns whether
|
||||
// the application has performance optimizations enabled.
|
||||
func (c Configuration) GetEnableOptimizations() bool {
|
||||
return c.EnableOptimizations
|
||||
}
|
||||
|
||||
// GetFireMethodNotAllowed returns the Configuration#FireMethodNotAllowed.
|
||||
func (c Configuration) GetFireMethodNotAllowed() bool {
|
||||
return c.FireMethodNotAllowed
|
||||
}
|
||||
|
||||
// GetDisableBodyConsumptionOnUnmarshal returns the Configuration#GetDisableBodyConsumptionOnUnmarshal,
|
||||
// manages the reading behavior of the context's body readers/binders.
|
||||
// If returns true then the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`
|
||||
|
@ -1149,6 +1166,10 @@ func WithConfiguration(c Configuration) Configurator {
|
|||
main.DisablePathCorrectionRedirection = v
|
||||
}
|
||||
|
||||
if v := c.EnablePathIntelligence; v {
|
||||
main.EnablePathIntelligence = v
|
||||
}
|
||||
|
||||
if v := c.EnablePathEscape; v {
|
||||
main.EnablePathEscape = v
|
||||
}
|
||||
|
|
|
@ -146,6 +146,7 @@ func TestConfigurationYAML(t *testing.T) {
|
|||
yamlConfigurationContents := `
|
||||
DisablePathCorrection: false
|
||||
DisablePathCorrectionRedirection: true
|
||||
EnablePathIntelligence: true
|
||||
EnablePathEscape: false
|
||||
FireMethodNotAllowed: true
|
||||
EnableOptimizations: true
|
||||
|
@ -175,6 +176,10 @@ Other:
|
|||
t.Fatalf("error on TestConfigurationYAML: Expected DisablePathCorrectionRedirection %v but got %v", expected, c.DisablePathCorrectionRedirection)
|
||||
}
|
||||
|
||||
if expected := true; c.EnablePathIntelligence != expected {
|
||||
t.Fatalf("error on TestConfigurationYAML: Expected EnablePathIntelligence %v but got %v", expected, c.EnablePathIntelligence)
|
||||
}
|
||||
|
||||
if expected := false; c.EnablePathEscape != expected {
|
||||
t.Fatalf("error on TestConfigurationYAML: Expected EnablePathEscape %v but got %v", expected, c.EnablePathEscape)
|
||||
}
|
||||
|
|
|
@ -25,26 +25,24 @@ type ConfigurationReadOnly interface {
|
|||
// then the Router checks if /home handler exists, if yes,
|
||||
// (permant)redirects the client to the correct path /home.
|
||||
GetDisablePathCorrection() bool
|
||||
|
||||
// GetDisablePathCorrectionRedirection returns the Configuration#DisablePathCorrectionRedirection field.
|
||||
// GetDisablePathCorrectionRedirection returns the Configuration.DisablePathCorrectionRedirection field.
|
||||
// If DisablePathCorrectionRedirection set to true then it will handle paths as they are.
|
||||
// it will fire the handler of the matching route without
|
||||
// the last slash ("/") instead of send a redirection status.
|
||||
GetDisablePathCorrectionRedirection() bool
|
||||
|
||||
// GetEnablePathIntelligence returns the Configuration.EnablePathIntelligence field.
|
||||
GetEnablePathIntelligence() bool
|
||||
// GetEnablePathEscape is the configuration.EnablePathEscape,
|
||||
// returns true when its escapes the path, the named parameters (if any).
|
||||
GetEnablePathEscape() bool
|
||||
|
||||
// GetForceLowercaseRouting returns the value of the `ForceLowercaseRouting` setting.
|
||||
GetForceLowercaseRouting() bool
|
||||
// GetFireMethodNotAllowed returns the configuration.FireMethodNotAllowed.
|
||||
GetFireMethodNotAllowed() bool
|
||||
|
||||
// GetEnableOptimizations returns whether
|
||||
// the application has performance optimizations enabled.
|
||||
GetEnableOptimizations() bool
|
||||
|
||||
// GetFireMethodNotAllowed returns the configuration.FireMethodNotAllowed.
|
||||
GetFireMethodNotAllowed() bool
|
||||
// GetDisableBodyConsumptionOnUnmarshal returns the configuration.GetDisableBodyConsumptionOnUnmarshal,
|
||||
// manages the reading behavior of the context's body readers/binders.
|
||||
// If returns true then the body consumption by the `context.UnmarshalBody/ReadJSON/ReadXML`
|
||||
|
|
|
@ -351,7 +351,7 @@ type Context interface {
|
|||
// this request based on subdomain and request path.
|
||||
//
|
||||
// Order may change.
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/routing/not-found-suggests
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/routing/intelligence/manual
|
||||
FindClosest(n int) []string
|
||||
// IsWWW returns true if the current subdomain (if any) is www.
|
||||
IsWWW() bool
|
||||
|
@ -1812,7 +1812,7 @@ func (ctx *context) Subdomain() (subdomain string) {
|
|||
// this request based on subdomain and request path.
|
||||
//
|
||||
// Order may change.
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/routing/not-found-suggests
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/routing/intelligence/manual
|
||||
func (ctx *context) FindClosest(n int) []string {
|
||||
return ctx.Application().FindClosestPaths(ctx.Subdomain(), ctx.Path(), n)
|
||||
}
|
||||
|
|
|
@ -229,3 +229,19 @@ func (api *APIContainer) Any(relativePath string, handlersFn ...interface{}) (ro
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// OnErrorCode registers a handlers chain for this `Party` for a specific HTTP status code.
|
||||
// Read more at: http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
// Look `OnAnyErrorCode` too.
|
||||
func (api *APIContainer) OnErrorCode(statusCode int, handlersFn ...interface{}) []*Route {
|
||||
handlers := api.convertHandlerFuncs("/{tail:path}", handlersFn...)
|
||||
return api.Self.OnErrorCode(statusCode, handlers...)
|
||||
}
|
||||
|
||||
// OnAnyErrorCode registers a handlers chain for all error codes
|
||||
// (4xxx and 5xxx, change the `ClientErrorCodes` and `ServerErrorCodes` variables to modify those)
|
||||
// Look `OnErrorCode` too.
|
||||
func (api *APIContainer) OnAnyErrorCode(handlersFn ...interface{}) []*Route {
|
||||
handlers := api.convertHandlerFuncs("/{tail:path}", handlersFn...)
|
||||
return api.Self.OnAnyErrorCode(handlers...)
|
||||
}
|
||||
|
|
|
@ -417,6 +417,16 @@ func (h *routerHandler) HandleRequest(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
if config.GetEnablePathIntelligence() && method == http.MethodGet {
|
||||
closestPaths := ctx.FindClosest(1)
|
||||
if len(closestPaths) > 0 {
|
||||
u := ctx.Request().URL
|
||||
u.Path = closestPaths[0]
|
||||
ctx.Redirect(u.String(), http.StatusMovedPermanently)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ctx.StatusCode(http.StatusNotFound)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user