mirror of
https://github.com/kataras/iris.git
synced 2026-01-08 12:31:58 +00:00
Update to version 12.1.7
Former-commit-id: 3e214ab6b6da4d1c6e4a66180a4ccfa61c0879ae
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -80,13 +81,20 @@ func (repo *repository) getAll() []*Route {
|
||||
return repo.routes
|
||||
}
|
||||
|
||||
func (repo *repository) register(route *Route) {
|
||||
func (repo *repository) register(route *Route, rule RouteRegisterRule) (*Route, error) {
|
||||
for i, r := range repo.routes {
|
||||
// 14 August 2019 allow register same path pattern with different macro functions,
|
||||
// see #1058
|
||||
if route.DeepEqual(r) {
|
||||
// replace existing with the latest one.
|
||||
repo.routes = append(repo.routes[:i], repo.routes[i+1:]...)
|
||||
if rule == RouteSkip {
|
||||
return r, nil
|
||||
} else if rule == RouteError {
|
||||
return nil, fmt.Errorf("new route: %s conflicts with an already registered one: %s route", route.String(), r.String())
|
||||
} else {
|
||||
// replace existing with the latest one, the default behavior.
|
||||
repo.routes = append(repo.routes[:i], repo.routes[i+1:]...)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -97,6 +105,7 @@ func (repo *repository) register(route *Route) {
|
||||
}
|
||||
|
||||
repo.pos[route.tmpl.Src] = len(repo.routes) - 1
|
||||
return route, nil
|
||||
}
|
||||
|
||||
// APIBuilder the visible API for constructing the router
|
||||
@@ -140,6 +149,8 @@ type APIBuilder struct {
|
||||
|
||||
// the per-party (and its children) execution rules for begin, main and done handlers.
|
||||
handlerExecutionRules ExecutionRules
|
||||
// the per-party (and its children) route registration rule, see `SetRegisterRule`.
|
||||
routeRegisterRule RouteRegisterRule
|
||||
}
|
||||
|
||||
var _ Party = (*APIBuilder)(nil)
|
||||
@@ -210,15 +221,35 @@ func (api *APIBuilder) SetExecutionRules(executionRules ExecutionRules) Party {
|
||||
return api
|
||||
}
|
||||
|
||||
// RouteRegisterRule is a type of uint8.
|
||||
// Defines the register rule for new routes that already exists.
|
||||
// Available values are: RouteOverride, RouteSkip and RouteError.
|
||||
//
|
||||
// See `Party#SetRegisterRule`.
|
||||
type RouteRegisterRule uint8
|
||||
|
||||
const (
|
||||
// RouteOverride an existing route with the new one, the default rule.
|
||||
RouteOverride RouteRegisterRule = iota
|
||||
// RouteSkip registering a new route twice.
|
||||
RouteSkip
|
||||
// RouteError log when a route already exists, shown after the `Build` state,
|
||||
// server never starts.
|
||||
RouteError
|
||||
)
|
||||
|
||||
// SetRegisterRule sets a `RouteRegisterRule` for this Party and its children.
|
||||
// Available values are: RouteOverride (the default one), RouteSkip and RouteError.
|
||||
func (api *APIBuilder) SetRegisterRule(rule RouteRegisterRule) Party {
|
||||
api.routeRegisterRule = rule
|
||||
return api
|
||||
}
|
||||
|
||||
// CreateRoutes returns a list of Party-based Routes.
|
||||
// It does NOT registers the route. Use `Handle, Get...` methods instead.
|
||||
// This method can be used for third-parties Iris helpers packages and tools
|
||||
// that want a more detailed view of Party-based Routes before take the decision to register them.
|
||||
func (api *APIBuilder) CreateRoutes(methods []string, relativePath string, handlers ...context.Handler) []*Route {
|
||||
// if relativePath[0] != '/' {
|
||||
// return nil, errors.New("path should start with slash and should not be empty")
|
||||
// }
|
||||
|
||||
if len(methods) == 0 || methods[0] == "ALL" || methods[0] == "ANY" { // then use like it was .Any
|
||||
return api.Any(relativePath, handlers...)
|
||||
}
|
||||
@@ -327,6 +358,7 @@ func (api *APIBuilder) Handle(method string, relativePath string, handlers ...co
|
||||
routes := api.CreateRoutes([]string{method}, relativePath, handlers...)
|
||||
|
||||
var route *Route // the last one is returned.
|
||||
var err error
|
||||
for _, route = range routes {
|
||||
if route == nil {
|
||||
break
|
||||
@@ -334,7 +366,10 @@ func (api *APIBuilder) Handle(method string, relativePath string, handlers ...co
|
||||
// global
|
||||
|
||||
route.topLink = api.routes.getRelative(route)
|
||||
api.routes.register(route)
|
||||
if route, err = api.routes.register(route, api.routeRegisterRule); err != nil {
|
||||
api.errors.Add(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return route
|
||||
@@ -441,7 +476,10 @@ func (api *APIBuilder) HandleDir(requestPath, directory string, opts ...DirOptio
|
||||
|
||||
for _, route := range routes {
|
||||
route.MainHandlerName = `HandleDir(directory: "` + directory + `")`
|
||||
api.routes.register(route)
|
||||
if _, err := api.routes.register(route, api.routeRegisterRule); err != nil {
|
||||
api.errors.Add(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return getRoute
|
||||
@@ -496,6 +534,7 @@ func (api *APIBuilder) Party(relativePath string, handlers ...context.Handler) P
|
||||
relativePath: fullpath,
|
||||
allowMethods: allowMethods,
|
||||
handlerExecutionRules: api.handlerExecutionRules,
|
||||
routeRegisterRule: api.routeRegisterRule,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,9 @@ type Party interface {
|
||||
//
|
||||
// Example: https://github.com/kataras/iris/tree/master/_examples/mvc/middleware/without-ctx-next
|
||||
SetExecutionRules(executionRules ExecutionRules) Party
|
||||
// SetRegisterRule sets a `RouteRegisterRule` for this Party and its children.
|
||||
// Available values are: RouteOverride (the default one), RouteSkip and RouteError.
|
||||
SetRegisterRule(rule RouteRegisterRule) Party
|
||||
// Handle registers a route to the server's router.
|
||||
// if empty method is passed then handler(s) are being registered to all methods, same as .Any.
|
||||
//
|
||||
|
||||
60
core/router/route_register_rule_test.go
Normal file
60
core/router/route_register_rule_test.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package router_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/kataras/iris/v12/core/router"
|
||||
"github.com/kataras/iris/v12/httptest"
|
||||
)
|
||||
|
||||
func TestRegisterRule(t *testing.T) {
|
||||
app := iris.New()
|
||||
v1 := app.Party("/v1")
|
||||
v1.SetRegisterRule(iris.RouteSkip)
|
||||
|
||||
getHandler := func(ctx iris.Context) {
|
||||
ctx.Writef("[get] %s", ctx.Method())
|
||||
}
|
||||
|
||||
anyHandler := func(ctx iris.Context) {
|
||||
ctx.Writef("[any] %s", ctx.Method())
|
||||
}
|
||||
|
||||
getRoute := v1.Get("/", getHandler)
|
||||
v1.Any("/", anyHandler)
|
||||
if route := v1.Get("/", getHandler); !reflect.DeepEqual(route, getRoute) {
|
||||
t.Fatalf("expected route to be equal with the original get route")
|
||||
}
|
||||
|
||||
// test RouteSkip.
|
||||
e := httptest.New(t, app, httptest.LogLevel("error"))
|
||||
testRegisterRule(e, "[get] GET")
|
||||
|
||||
// test RouteOverride (default behavior).
|
||||
v1.SetRegisterRule(iris.RouteOverride)
|
||||
v1.Any("/", anyHandler)
|
||||
app.RefreshRouter()
|
||||
testRegisterRule(e, "[any] GET")
|
||||
|
||||
// test RouteError.
|
||||
v1.SetRegisterRule(iris.RouteError)
|
||||
if route := v1.Get("/", getHandler); route != nil {
|
||||
t.Fatalf("expected duplicated route, with RouteError rule, to be nil but got: %#+v", route)
|
||||
}
|
||||
if expected, got := 1, len(v1.GetReporter().Errors); expected != got {
|
||||
t.Fatalf("expected api builder's errors length to be: %d but got: %d", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func testRegisterRule(e *httptest.Expect, expectedGetBody string) {
|
||||
for _, method := range router.AllMethods {
|
||||
tt := e.Request(method, "/v1").Expect().Status(httptest.StatusOK).Body()
|
||||
if method == iris.MethodGet {
|
||||
tt.Equal(expectedGetBody)
|
||||
} else {
|
||||
tt.Equal("[any] " + method)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user