PNG  IHDR  8] PLTE S =tRNS   PNG  IHDR  8] PLTE S =tRNS   REDROOM
PHP 7.4.33
Preview: routing_tree.go Size: 7.48 KB
/proc/thread-self/root/opt/golang/1.22.0/src/net/http/routing_tree.go

// 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.

// This file implements a decision tree for fast matching of requests to
// patterns.
//
// The root of the tree branches on the host of the request.
// The next level branches on the method.
// The remaining levels branch on consecutive segments of the path.
//
// The "more specific wins" precedence rule can result in backtracking.
// For example, given the patterns
//     /a/b/z
//     /a/{x}/c
// we will first try to match the path "/a/b/c" with /a/b/z, and
// when that fails we will try against /a/{x}/c.

package http

import (
	"strings"
)

// A routingNode is a node in the decision tree.
// The same struct is used for leaf and interior nodes.
type routingNode struct {
	// A leaf node holds a single pattern and the Handler it was registered
	// with.
	pattern *pattern
	handler Handler

	// An interior node maps parts of the incoming request to child nodes.
	// special children keys:
	//     "/"	trailing slash (resulting from {$})
	//	   ""   single wildcard
	//	   "*"  multi wildcard
	children   mapping[string, *routingNode]
	emptyChild *routingNode // optimization: child with key ""
}

// addPattern adds a pattern and its associated Handler to the tree
// at root.
func (root *routingNode) addPattern(p *pattern, h Handler) {
	// First level of tree is host.
	n := root.addChild(p.host)
	// Second level of tree is method.
	n = n.addChild(p.method)
	// Remaining levels are path.
	n.addSegments(p.segments, p, h)
}

// addSegments adds the given segments to the tree rooted at n.
// If there are no segments, then n is a leaf node that holds
// the given pattern and handler.
func (n *routingNode) addSegments(segs []segment, p *pattern, h Handler) {
	if len(segs) == 0 {
		n.set(p, h)
		return
	}
	seg := segs[0]
	if seg.multi {
		if len(segs) != 1 {
			panic("multi wildcard not last")
		}
		n.addChild("*").set(p, h)
	} else if seg.wild {
		n.addChild("").addSegments(segs[1:], p, h)
	} else {
		n.addChild(seg.s).addSegments(segs[1:], p, h)
	}
}

// set sets the pattern and handler for n, which
// must be a leaf node.
func (n *routingNode) set(p *pattern, h Handler) {
	if n.pattern != nil || n.handler != nil {
		panic("non-nil leaf fields")
	}
	n.pattern = p
	n.handler = h
}

// addChild adds a child node with the given key to n
// if one does not exist, and returns the child.
func (n *routingNode) addChild(key string) *routingNode {
	if key == "" {
		if n.emptyChild == nil {
			n.emptyChild = &routingNode{}
		}
		return n.emptyChild
	}
	if c := n.findChild(key); c != nil {
		return c
	}
	c := &routingNode{}
	n.children.add(key, c)
	return c
}

// findChild returns the child of n with the given key, or nil
// if there is no child with that key.
func (n *routingNode) findChild(key string) *routingNode {
	if key == "" {
		return n.emptyChild
	}
	r, _ := n.children.find(key)
	return r
}

// match returns the leaf node under root that matches the arguments, and a list
// of values for pattern wildcards in the order that the wildcards appear.
// For example, if the request path is "/a/b/c" and the pattern is "/{x}/b/{y}",
// then the second return value will be []string{"a", "c"}.
func (root *routingNode) match(host, method, path string) (*routingNode, []string) {
	if host != "" {
		// There is a host. If there is a pattern that specifies that host and it
		// matches, we are done. If the pattern doesn't match, fall through to
		// try patterns with no host.
		if l, m := root.findChild(host).matchMethodAndPath(method, path); l != nil {
			return l, m
		}
	}
	return root.emptyChild.matchMethodAndPath(method, path)
}

// matchMethodAndPath matches the method and path.
// Its return values are the same as [routingNode.match].
// The receiver should be a child of the root.
func (n *routingNode) matchMethodAndPath(method, path string) (*routingNode, []string) {
	if n == nil {
		return nil, nil
	}
	if l, m := n.findChild(method).matchPath(path, nil); l != nil {
		// Exact match of method name.
		return l, m
	}
	if method == "HEAD" {
		// GET matches HEAD too.
		if l, m := n.findChild("GET").matchPath(path, nil); l != nil {
			return l, m
		}
	}
	// No exact match; try patterns with no method.
	return n.emptyChild.matchPath(path, nil)
}

// matchPath matches a path.
// Its return values are the same as [routingNode.match].
// matchPath calls itself recursively. The matches argument holds the wildcard matches
// found so far.
func (n *routingNode) matchPath(path string, matches []string) (*routingNode, []string) {
	if n == nil {
		return nil, nil
	}
	// If path is empty, then we are done.
	// If n is a leaf node, we found a match; return it.
	// If n is an interior node (which means it has a nil pattern),
	// then we failed to match.
	if path == "" {
		if n.pattern == nil {
			return nil, nil
		}
		return n, matches
	}
	// Get the first segment of path.
	seg, rest := firstSegment(path)
	// First try matching against patterns that have a literal for this position.
	// We know by construction that such patterns are more specific than those
	// with a wildcard at this position (they are either more specific, equivalent,
	// or overlap, and we ruled out the first two when the patterns were registered).
	if n, m := n.findChild(seg).matchPath(rest, matches); n != nil {
		return n, m
	}
	// If matching a literal fails, try again with patterns that have a single
	// wildcard (represented by an empty string in the child mapping).
	// Again, by construction, patterns with a single wildcard must be more specific than
	// those with a multi wildcard.
	// We skip this step if the segment is a trailing slash, because single wildcards
	// don't match trailing slashes.
	if seg != "/" {
		if n, m := n.emptyChild.matchPath(rest, append(matches, seg)); n != nil {
			return n, m
		}
	}
	// Lastly, match the pattern (there can be at most one) that has a multi
	// wildcard in this position to the rest of the path.
	if c := n.findChild("*"); c != nil {
		// Don't record a match for a nameless wildcard (which arises from a
		// trailing slash in the pattern).
		if c.pattern.lastSegment().s != "" {
			matches = append(matches, pathUnescape(path[1:])) // remove initial slash
		}
		return c, matches
	}
	return nil, nil
}

// firstSegment splits path into its first segment, and the rest.
// The path must begin with "/".
// If path consists of only a slash, firstSegment returns ("/", "").
// The segment is returned unescaped, if possible.
func firstSegment(path string) (seg, rest string) {
	if path == "/" {
		return "/", ""
	}
	path = path[1:] // drop initial slash
	i := strings.IndexByte(path, '/')
	if i < 0 {
		i = len(path)
	}
	return pathUnescape(path[:i]), path[i:]
}

// matchingMethods adds to methodSet all the methods that would result in a
// match if passed to routingNode.match with the given host and path.
func (root *routingNode) matchingMethods(host, path string, methodSet map[string]bool) {
	if host != "" {
		root.findChild(host).matchingMethodsPath(path, methodSet)
	}
	root.emptyChild.matchingMethodsPath(path, methodSet)
	if methodSet["GET"] {
		methodSet["HEAD"] = true
	}
}

func (n *routingNode) matchingMethodsPath(path string, set map[string]bool) {
	if n == nil {
		return
	}
	n.children.eachPair(func(method string, c *routingNode) bool {
		if p, _ := c.matchPath(path, nil); p != nil {
			set[method] = true
		}
		return true
	})
	// Don't look at the empty child. If there were an empty
	// child, it would match on any method, but we only
	// call this when we fail to match on a method.
}

Directory Contents

Dirs: 9 × Files: 64

Name Size Perms Modified Actions
cgi DIR
- drwxr-xr-x 2024-02-02 18:09:55
Edit Download
cookiejar DIR
- drwxr-xr-x 2024-02-02 18:09:55
Edit Download
fcgi DIR
- drwxr-xr-x 2024-02-02 18:09:55
Edit Download
httptest DIR
- drwxr-xr-x 2024-02-02 18:09:55
Edit Download
httptrace DIR
- drwxr-xr-x 2024-02-02 18:09:55
Edit Download
httputil DIR
- drwxr-xr-x 2024-02-02 18:09:55
Edit Download
internal DIR
- drwxr-xr-x 2024-02-02 18:09:55
Edit Download
pprof DIR
- drwxr-xr-x 2024-02-02 18:09:55
Edit Download
testdata DIR
- drwxr-xr-x 2024-02-02 18:09:55
Edit Download
3.01 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
33.40 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
46.07 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
63.24 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
1.56 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
11.53 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
19.26 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
3.42 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
2.04 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
560 B lrw-r--r-- 2024-02-02 18:09:55
Edit Download
5.38 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
8.43 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
3.52 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
2.62 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
30.36 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
46.70 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
357.28 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
812 B lrw-r--r-- 2024-02-02 18:09:55
Edit Download
1.04 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
7.90 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
6.05 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
5.13 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
5.22 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
900 B lrw-r--r-- 2024-02-02 18:09:55
Edit Download
4.94 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
1.68 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
2.95 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
517 B lrw-r--r-- 2024-02-02 18:09:55
Edit Download
1.91 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
15.17 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
14.50 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
1.16 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
2.38 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
9.70 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
48.34 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
23.30 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
42.39 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
11.10 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
4.17 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
9.81 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
6.89 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
23.63 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
566 B lrw-r--r-- 2024-02-02 18:09:55
Edit Download
11.80 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
3.95 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
4.02 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
7.48 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
6.89 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
5.60 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
120.67 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
6.95 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
192.54 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
7.90 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
9.56 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
12.90 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
7.45 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
30.89 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
9.13 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
87.81 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
362 B lrw-r--r-- 2024-02-02 18:09:55
Edit Download
364 B lrw-r--r-- 2024-02-02 18:09:55
Edit Download
6.05 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
186.06 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download
3.22 KB lrw-r--r-- 2024-02-02 18:09:55
Edit Download

If ZipArchive is unavailable, a .tar will be created (no compression).
 !"#$%&'(()*+,-./00123456789 t\ wIDATx ]ys  47Y ƒ -  "  Rv  < f{Ɛ $k l L > L  ~h^ 1  [  r G t& h  l F z3O Y ! p A(_g̷ E8 )S 8 c  Kb"z ~ 5 J xAL WU <  *  5 m;W a pB h ~P J 2 3 6 ҙ .Ƹ P i  4g F R L P ΪK/D  M v (a3 k J Œ4N5* SH ` SdJ z  O J Xՠ V>u ߱ BE&L b2 ?2` tX+  c CB A$ i b C ĀMB E : /  # Dx &l =q Ty  0 \p I ( L Ǎ { e 4k ;`u^ヲ eP!( d {  )T A 8 O;Ě n >;s6 !  :Nx `[S D HU ~ q›J F} a g*D 49 / pn k h (t 8NxƐF _!r չ7 ZR R׷ q/5") Ӎ NY 0 x sZ!   o  fu  ,  K"$ ? pg  㕣=  1» {h " fh7    y  } € +7  $ y " X —ą - G P u 4 m >J 5 L =V ' ^@I p ?MS xЌ XV P ! h "C NS9B8̢ ]!K  e   zA , ӏkbY  !< XQ ٿyS| *" f { w  4@[S <  # 0 ! js [m  =,~ o "ݎ DHf Wo $ g ! Vԅ t mB /y Wf V4񺍸 c+@x?  B ~u " xUN e 0 BĂ) ~J pz! 7y6]l Ԥ@ P a< O /DHC `≻  N m"$  0ObB }{ x AO FCG D R ^ "B  { WDH  UR l@ T #  +"d T ; 0 i  D}. 7 ` ' ] w rE &S i ƕiTD EL P _ u h $ Ա FG wVD G L R Zf ' .!] J /ZR oGЍs Mr Ĥ ʬ 3 Q [3 cL ` ^ p + ( F;# B 5 '  2Y f [  ϶R0e }  E 7 6M aۮ H <& n % L] E}Up x紉, Uw' Q  Ǯշo k ވۙ 0N94 VX5 xEDE l D #֤ } C o )W :  ^ s 9  bRf iX5u ཱི 4 :[  T 1. | [E 2ؽ Iy\ : o x K G 5 ylP ' uK E ftb/i[3 .g _  [3M n G, #NwQ5~  ؚ) | n =Ц"x qg gB ` 듘 ~ x w ? ? R~  _ u. &VQ K˻   H C ( TN˄+ `C dA nB׭ D 3"Z G ê ^k H_ /- ~ " R_  .8 Z_ 6@ o  xg  uP ? 3լ @7AM!  E7^ - =V L  x  g-D0  CtmW 7  O  G _ WD0 g C  w1 r d w : a | \  *" f nֳ ^ H# f L ` Z ۽hV  }S F r0Ù Bć5r] @! NL iQ]{s^=4 d  WD  "  "   M; t" 8 5 e dL| "-*st" ) SWD ?R[S e ooF  20.D ? bo =) A i o d ģ ZҰaO @E =) i D a &ܟa CϞ y6 ,<%{^x%{f8? `iw^ ?/ M * IEND B`