1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-31 08:47:03 +00:00

new feature: handle different param types in the exact same path pattern

implements https://github.com/kataras/iris/issues/1315


Former-commit-id: 3e9276f2a95d6fc7c10fbf91186d041dcba72611
This commit is contained in:
Gerasimos (Makis) Maropoulos
2019-07-29 23:09:22 +03:00
parent c44fc6e1de
commit 700dcc8005
10 changed files with 168 additions and 28 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/kataras/iris/context"
"github.com/kataras/iris/core/errors"
"github.com/kataras/iris/macro"
macroHandler "github.com/kataras/iris/macro/handler"
)
// MethodNone is a Virtual method
@@ -109,6 +110,20 @@ func (repo *repository) get(routeName string) *Route {
return nil
}
func (repo *repository) getRelative(r *Route) *Route {
if r.tmpl.IsTrailing() || !macroHandler.CanMakeHandler(r.tmpl) {
return nil
}
for _, route := range repo.routes {
if r.Subdomain == route.Subdomain && r.Method == route.Method && r.FormattedPath == route.FormattedPath && !route.tmpl.IsTrailing() {
return route
}
}
return nil
}
func (repo *repository) getByPath(tmplPath string) *Route {
if repo.pos != nil {
if idx, ok := repo.pos[tmplPath]; ok {
@@ -345,6 +360,8 @@ func (api *APIBuilder) Handle(method string, relativePath string, handlers ...co
var route *Route // the last one is returned.
for _, route = range routes {
// global
route.topLink = api.routes.getRelative(route)
api.routes.register(route)
}

View File

@@ -5,11 +5,12 @@ import (
"sort"
"strings"
"github.com/kataras/golog"
"github.com/kataras/iris/context"
"github.com/kataras/iris/core/errors"
"github.com/kataras/iris/core/netutil"
macroHandler "github.com/kataras/iris/macro/handler"
"github.com/kataras/golog"
)
// RequestHandler the middle man between acquiring a context and releasing it.
@@ -116,29 +117,63 @@ func (h *routerHandler) Build(provider RoutesProvider) error {
})
for _, r := range registeredRoutes {
// build the r.Handlers based on begin and done handlers, if any.
r.BuildHandlers()
if r.topLink != nil {
bindMultiParamTypesHandler(r.topLink, r)
}
}
for _, r := range registeredRoutes {
if r.Subdomain != "" {
h.hosts = true
}
// the only "bad" with this is if the user made an error
// on route, it will be stacked shown in this build state
// and no in the lines of the user's action, they should read
// the docs better. Or TODO: add a link here in order to help new users.
if err := h.addRoute(r); err != nil {
// node errors:
rp.Add("%v -> %s", err, r.String())
continue
if r.topLink == nil {
// build the r.Handlers based on begin and done handlers, if any.
r.BuildHandlers()
// the only "bad" with this is if the user made an error
// on route, it will be stacked shown in this build state
// and no in the lines of the user's action, they should read
// the docs better. Or TODO: add a link here in order to help new users.
if err := h.addRoute(r); err != nil {
// node errors:
rp.Add("%v -> %s", err, r.String())
continue
}
}
golog.Debugf(r.Trace())
golog.Debugf(r.Trace()) // keep log different parameter types in the same path as different routes.
}
return rp.Return()
}
func bindMultiParamTypesHandler(top *Route, r *Route) {
r.BuildHandlers()
h := r.Handlers[1:] // remove the macro evaluator handler as we manually check below.
f := macroHandler.MakeFilter(r.tmpl)
if f == nil {
return // should never happen, previous checks made to set the top link.
}
decisionHandler := func(ctx context.Context) {
currentRouteName := ctx.RouteName()
if f(ctx) {
ctx.SetCurrentRouteName(r.Name)
ctx.HandlerIndex(0)
ctx.Do(h)
return
}
ctx.SetCurrentRouteName(currentRouteName)
ctx.StatusCode(http.StatusOK)
ctx.Next()
}
r.topLink.beginHandlers = append(context.Handlers{decisionHandler}, r.topLink.beginHandlers...)
}
func (h *routerHandler) HandleRequest(ctx context.Context) {
method := ctx.Method()
path := ctx.Path()

View File

@@ -40,6 +40,8 @@ type Route struct {
// route, manually or automatic by the framework,
// get the route by `Application#GetRouteByPath(staticSite.RequestPath)`.
StaticSites []context.StaticSite `json:"staticSites"`
topLink *Route
}
// NewRoute returns a new route based on its method,