Source File
routing_index.go
Belonging Package
net/http
// Copyright 2023 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package httpimport// A routingIndex optimizes conflict detection by indexing patterns.//// The basic idea is to rule out patterns that cannot conflict with a given// pattern because they have a different literal in a corresponding segment.// See the comments in [routingIndex.possiblyConflictingPatterns] for more details.type routingIndex struct {// map from a particular segment position and value to all registered patterns// with that value in that position.// For example, the key {1, "b"} would hold the patterns "/a/b" and "/a/b/c"// but not "/a", "b/a", "/a/c" or "/a/{x}".segments map[routingIndexKey][]*pattern// All patterns that end in a multi wildcard (including trailing slash).// We do not try to be clever about indexing multi patterns, because there// are unlikely to be many of them.multis []*pattern}type routingIndexKey struct {pos int // 0-based segment positions string // literal, or empty for wildcard}func ( *routingIndex) ( *pattern) {if .lastSegment().multi {.multis = append(.multis, )} else {if .segments == nil {.segments = map[routingIndexKey][]*pattern{}}for , := range .segments {:= routingIndexKey{pos: , s: ""}if !.wild {.s = .s}.segments[] = append(.segments[], )}}}// possiblyConflictingPatterns calls f on all patterns that might conflict with// pat. If f returns a non-nil error, possiblyConflictingPatterns returns immediately// with that error.//// To be correct, possiblyConflictingPatterns must include all patterns that// might conflict. But it may also include patterns that cannot conflict.// For instance, an implementation that returns all registered patterns is correct.// We use this fact throughout, simplifying the implementation by returning more// patterns that we might need to.func ( *routingIndex) ( *pattern, func(*pattern) error) ( error) {// Terminology:// dollar pattern: one ending in "{$}"// multi pattern: one ending in a trailing slash or "{x...}" wildcard// ordinary pattern: neither of the above// apply f to all the pats, stopping on error.:= func( []*pattern) error {if != nil {return}for , := range {= ()if != nil {return}}return nil}// Our simple indexing scheme doesn't try to prune multi patterns; assume// any of them can match the argument.if := (.multis); != nil {return}if .lastSegment().s == "/" {// All paths that a dollar pattern matches end in a slash; no paths that// an ordinary pattern matches do. So only other dollar or multi// patterns can conflict with a dollar pattern. Furthermore, conflicting// dollar patterns must have the {$} in the same position.return (.segments[routingIndexKey{s: "/", pos: len(.segments) - 1}])}// For ordinary and multi patterns, the only conflicts can be with a multi,// or a pattern that has the same literal or a wildcard at some literal// position.// We could intersect all the possible matches at each position, but we// do something simpler: we find the position with the fewest patterns.var , []*pattern:= math.MaxInt:= falsefor , := range .segments {if .multi {break}if !.wild {= true:= .segments[routingIndexKey{s: .s, pos: }]:= .segments[routingIndexKey{s: "", pos: }]if := len() + len(); < {===}}}if {()()return}// This pattern is all wildcards.// Check it against everything.for , := range .segments {()}return}
![]() |
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |