diff --git a/_examples/file-server/basic/assets/index.html b/_examples/file-server/basic/assets/index.html new file mode 100644 index 00000000..06651a45 --- /dev/null +++ b/_examples/file-server/basic/assets/index.html @@ -0,0 +1 @@ +

Hello index

\ No newline at end of file diff --git a/_examples/routing/custom-context/method-overriding/main.go b/_examples/routing/custom-context/method-overriding/main.go index bfed8efb..8747be93 100644 --- a/_examples/routing/custom-context/method-overriding/main.go +++ b/_examples/routing/custom-context/method-overriding/main.go @@ -20,8 +20,16 @@ type MyContext struct { var _ context.Context = &MyContext{} // optionally: validate on compile-time if MyContext implements context.Context. -// Optional Part 2: -// The only one important if you will override the Context with an embedded context.Context inside it. +// The only one important if you will override the Context +// with an embedded context.Context inside it. +// Required in order to run the handlers via this "*MyContext". +func (ctx *MyContext) Do(handlers context.Handlers) { + context.Do(ctx, handlers) +} + +// The second one important if you will override the Context +// with an embedded context.Context inside it. +// Required in order to run the chain of handlers via this "*MyContext". func (ctx *MyContext) Next() { context.Next(ctx) } @@ -40,11 +48,9 @@ func main() { app := iris.New() // app.Logger().SetLevel("debug") - // Register a view engine on .html files inside the ./view/** directory. - app.RegisterView(iris.HTML("./view", ".html")) - // The only one Required: - // here is how you define how your own context will be created and acquired from the iris' generic context pool. + // here is how you define how your own context will + // be created and acquired from the iris' generic context pool. app.ContextPool.Attach(func() context.Context { return &MyContext{ // Optional Part 3: @@ -52,6 +58,9 @@ func main() { } }) + // Register a view engine on .html files inside the ./view/** directory. + app.RegisterView(iris.HTML("./view", ".html")) + // register your route, as you normally do app.Handle("GET", "/", recordWhichContextJustForProofOfConcept, func(ctx context.Context) { // use the context's overridden HTML method. diff --git a/_examples/routing/dynamic-path/root-wildcard/main.go b/_examples/routing/dynamic-path/root-wildcard/main.go index 13eacb32..1be0d1ca 100644 --- a/_examples/routing/dynamic-path/root-wildcard/main.go +++ b/_examples/routing/dynamic-path/root-wildcard/main.go @@ -14,12 +14,13 @@ func main() { // / -> because of app.Get("/", ...) // /other/anything/here -> because of app.Get("/other/{paramother:path}", ...) // /other2/anything/here -> because of app.Get("/other2/{paramothersecond:path}", ...) - // /other2/static -> because of app.Get("/other2/static", ...) + // /other2/static2 -> because of app.Get("/other2/static", ...) // // It isn't conflicts with the rest of the routes, without routing performance cost! // // i.e /something/here/that/cannot/be/found/by/other/registered/routes/order/not/matters app.Get("/{p:path}", h) + // app.Get("/static/{p:path}", staticWildcardH) // this will handle only GET / app.Get("/", staticPath) @@ -36,7 +37,7 @@ func main() { app.Get("/other2/{paramothersecond:path}", other2) // this will handle only GET "/other2/static" - app.Get("/other2/static", staticPath) + app.Get("/other2/static2", staticPathOther2) app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed)) } @@ -46,6 +47,11 @@ func h(ctx context.Context) { ctx.WriteString(param) } +func staticWildcardH(ctx context.Context) { + param := ctx.Params().Get("p") + ctx.WriteString("from staticWildcardH: param=" + param) +} + func other(ctx context.Context) { param := ctx.Params().Get("paramother") ctx.Writef("from other: %s", param) @@ -57,5 +63,9 @@ func other2(ctx context.Context) { } func staticPath(ctx context.Context) { - ctx.Writef("from the static path: %s", ctx.Path()) + ctx.Writef("from the static path(/): %s", ctx.Path()) +} + +func staticPathOther2(ctx context.Context) { + ctx.Writef("from the static path(/other2/static2): %s", ctx.Path()) } diff --git a/context/context.go b/context/context.go index 5793c87c..2aff0e6b 100644 --- a/context/context.go +++ b/context/context.go @@ -758,6 +758,19 @@ func Next(ctx Context) { } } +// Do calls the SetHandlers(handlers) +// and executes the first handler, +// handlers should not be empty. +// +// It's used by the router, developers may use that +// to replace and execute handlers immediately. +func Do(ctx Context, handlers Handlers) { + if len(handlers) > 0 { + ctx.SetHandlers(handlers) + handlers[0](ctx) + } +} + // LimitRequestBodySize is a middleware which sets a request body size limit // for all next handlers in the chain. var LimitRequestBodySize = func(maxRequestBodySizeBytes int64) Handler { diff --git a/context/pool.go b/context/pool.go index a48d1026..30ab5523 100644 --- a/context/pool.go +++ b/context/pool.go @@ -21,6 +21,11 @@ func New(newFunc func() Context) *Pool { } // Attach changes the pool's return value Context. +// +// The new Context should explicitly define the `Next()` +// and `Do(context.Handlers)` functions. +// +// Example: https://github.com/kataras/iris/blob/master/_examples/routing/custom-context/method-overriding/main.go func (c *Pool) Attach(newFunc func() Context) { c.newFunc = newFunc } diff --git a/core/router/api_builder.go b/core/router/api_builder.go index dfa608e6..9f7e597f 100644 --- a/core/router/api_builder.go +++ b/core/router/api_builder.go @@ -658,6 +658,7 @@ func (rb *APIBuilder) StaticWeb(requestPath string, systemPath string) *Route { } requestPath = joinPath(fullpath, WildcardParam(paramName)) + // requestPath = fullpath + "/{file:path}" return rb.registerResourceRoute(requestPath, handler) } diff --git a/core/router/node/node.go b/core/router/node/node.go index 5c04c2a6..3cce094f 100644 --- a/core/router/node/node.go +++ b/core/router/node/node.go @@ -25,6 +25,8 @@ type node struct { // ErrDublicate returnned from `Add` when two or more routes have the same registered path. var ErrDublicate = errors.New("two or more routes have the same registered path") +/// TODO: clean up needed until v8.5 + // Add adds a node to the tree, returns an ErrDublicate error on failure. func (nodes *Nodes) Add(path string, handlers context.Handlers) error { // println("[Add] adding path: " + path) @@ -99,26 +101,29 @@ func (nodes *Nodes) add(path string, paramNames []string, handlers context.Handl // set the wildcard param name to the root and its children. wildcardIdx := strings.IndexByte(path, '*') wildcardParamName := "" - if wildcardIdx > 0 { + if wildcardIdx > 0 && len(paramNames) == 0 { wildcardParamName = path[wildcardIdx+1:] - path = path[0:wildcardIdx-1] + "/" // replace *paramName with single slash + + // if path[len(path)-1] == '/' { // if root wildcard, then add it as it's and return - if path == "/" { + rootWildcard := path == "/" + if rootWildcard { path += "/" // if root wildcard, then do it like "//" instead of simple "/" - n := &node{ - rootWildcard: true, - s: path, - wildcardParamName: wildcardParamName, - paramNames: paramNames, - handlers: handlers, - root: root, - } - *nodes = append(*nodes, n) - // println("1. nodes.Add path: " + path) - return } + n := &node{ + rootWildcard: rootWildcard, + s: path, + wildcardParamName: wildcardParamName, + paramNames: paramNames, + handlers: handlers, + root: root, + } + *nodes = append(*nodes, n) + // println("1. nodes.Add path: " + path) + return + } loop: @@ -127,6 +132,10 @@ loop: continue } + if len(n.paramNames) == 0 && n.wildcardParamName != "" { + continue + } + minlen := len(n.s) if len(path) < minlen { minlen = len(path) @@ -226,8 +235,9 @@ loop: handlers: handlers, root: root, } - // println("5. nodes.Add path: " + n.s) *nodes = append(*nodes, n) + + // println("5. node add on path: " + path + " n.s: " + n.s + " wildcard param: " + n.wildcardParamName) return } @@ -276,7 +286,7 @@ func (nodes Nodes) Exists(path string) bool { } func (nodes Nodes) findChild(path string, params []string) (*node, []string) { - // println("request path: " + path) + for _, n := range nodes { if n.s == ":" { paramEnd := strings.IndexByte(path, '/') @@ -309,8 +319,39 @@ func (nodes Nodes) findChild(path string, params []string) (*node, []string) { return n, append(params, path[1:]) } + // second conditional may be unnecessary + // because of the n.rootWildcard before, but do it. + if n.wildcardParamName != "" && len(path) > 2 { + // println("n has wildcard n.s: " + n.s + " on path: " + path) + // n.s = static/, path = static + + // println(n.s + " vs path: " + path) + + // we could have /other/ as n.s so + // we must do this check, remember: + // now wildcards live on their own nodes + if len(path) == len(n.s)-1 { + // then it's like: + // path = /other2 + // ns = /other2/ + if path == n.s[0:len(n.s)-1] { + return n, params + } + } + + // othwerwise path = /other2/dsadas + // ns= /other2/ + if strings.HasPrefix(path, n.s) { + if len(path) > len(n.s)+1 { + return n, append(params, path[len(n.s):]) // without slash + } + } + + } + if !strings.HasPrefix(path, n.s) { // fmt.Printf("---here root: %v, n.s: "+n.s+" and path: "+path+" is dynamic: %v , wildcardParamName: %s, children len: %v \n", n.root, n.isDynamic(), n.wildcardParamName, len(n.childrenNodes)) + // println(path + " n.s: " + n.s + " continue...") continue } @@ -322,6 +363,7 @@ func (nodes Nodes) findChild(path string, params []string) (*node, []string) { } child, childParamNames := n.childrenNodes.findChild(path[len(n.s):], params) + // print("childParamNames len: ") // println(len(childParamNames)) diff --git a/core/router/router_wildcard_root_test.go b/core/router/router_wildcard_root_test.go index 9ec72a17..2ca30652 100644 --- a/core/router/router_wildcard_root_test.go +++ b/core/router/router_wildcard_root_test.go @@ -117,13 +117,16 @@ func TestRouterWildcardRootManyAndRootStatic(t *testing.T) { // this feature is very important and can remove noumerous of previous hacks on our apps. {"GET", "/{p:path}", h, []testRouteRequest{ {"GET", "", "/other2almost/some", iris.StatusOK, same_as_request_path}, - // it's a request to /other , not other/something, therefore the root wildcard is the handler - {"GET", "", "/other", iris.StatusOK, same_as_request_path}, + }}, + {"GET", "/static/{p:path}", h, []testRouteRequest{ + {"GET", "", "/static", iris.StatusOK, same_as_request_path}, + {"GET", "", "/static/something/here", iris.StatusOK, same_as_request_path}, }}, {"GET", "/", h, []testRouteRequest{ {"GET", "", "/", iris.StatusOK, same_as_request_path}, }}, {"GET", "/other/{paramother:path}", h2, []testRouteRequest{ + {"GET", "", "/other", iris.StatusForbidden, same_as_request_path}, {"GET", "", "/other/wildcard", iris.StatusForbidden, same_as_request_path}, {"GET", "", "/other/wildcard/here", iris.StatusForbidden, same_as_request_path}, }},