| 223 | } |
| 224 | |
| 225 | func (app *App) next(c *DefaultCtx) (bool, error) { |
| 226 | methodInt := c.methodInt |
| 227 | treeHash := c.treePathHash |
| 228 | detectionPath := utils.UnsafeString(c.detectionPath) |
| 229 | path := utils.UnsafeString(c.path) |
| 230 | // Get stack length |
| 231 | tree, ok := app.treeStack[methodInt][treeHash] |
| 232 | if !ok { |
| 233 | tree = app.treeStack[methodInt][0] |
| 234 | } |
| 235 | indexRoute := max(c.indexRoute+1, 0) |
| 236 | |
| 237 | // Loop over the route stack starting from previous index; |
| 238 | // the clamp above plus the len(tree) guard keep tree[indexRoute] bounds-check free |
| 239 | for ; indexRoute < len(tree); indexRoute++ { |
| 240 | // Get *Route |
| 241 | route := tree[indexRoute] |
| 242 | |
| 243 | if route.mount { |
| 244 | continue |
| 245 | } |
| 246 | |
| 247 | // Check if it matches the request path |
| 248 | if !route.match(detectionPath, path, &c.values) { |
| 249 | continue |
| 250 | } |
| 251 | |
| 252 | if c.shouldSkipNonUseRoutes && !route.use { |
| 253 | continue |
| 254 | } |
| 255 | |
| 256 | // Pass route reference and param values |
| 257 | c.route = route |
| 258 | // Non use handler matched |
| 259 | if !route.use { |
| 260 | c.isMatched = true |
| 261 | } |
| 262 | // Execute first handler of route |
| 263 | if len(route.Handlers) > 0 { |
| 264 | c.indexHandler = 0 |
| 265 | c.indexRoute = indexRoute |
| 266 | return true, route.Handlers[0](c) |
| 267 | } |
| 268 | |
| 269 | return true, nil // Stop scanning the stack |
| 270 | } |
| 271 | |
| 272 | // If c.Next() does not match, return 404 |
| 273 | // If no match, scan stack again if other methods match the request |
| 274 | // Moved from app.handler because middleware may break the route chain |
| 275 | if c.shouldSkipNonUseRoutes { |
| 276 | return false, nil |
| 277 | } |
| 278 | |
| 279 | if c.isMatched { |
| 280 | return false, ErrNotFound |
| 281 | } |
| 282 | |