in src/go/util/httppattern/sort_impl.go [139:222]
func (hn *httpPatternTrieNode) traverse(result *MethodSlice) {
appendMethodOnCurrentNode := func() {
// Sort the method in alphabet order to generate deterministic sequence for better unit testing.
var sortedKeys []string
// Put the wildcard method in the end.
var wildMethodResult *lookupResult
for key, val := range hn.ResultMap {
if key == HttpMethodWildCard {
wildMethodResult = val
continue
}
sortedKeys = append(sortedKeys, key)
}
sort.Strings(sortedKeys)
for _, key := range sortedKeys {
if val, ok := hn.ResultMap[key]; ok {
result.AppendMethod(val.data.Method)
}
}
// Put the wildcard method in the end.
if wildMethodResult != nil {
result.AppendMethod(wildMethodResult.data.Method)
}
}
traverseChildren := func() {
var singleParameterChild *httpPatternTrieNode
var singleWildCardChild *httpPatternTrieNode
var doubleWildCardChild *httpPatternTrieNode
var exactMatchChildKeys []string
for key, child := range hn.Children {
switch key {
case SingleParameterKey:
singleParameterChild = child
case SingleWildCardKey:
singleWildCardChild = child
case DoubleWildCardKey:
doubleWildCardChild = child
default:
exactMatchChildKeys = append(exactMatchChildKeys, key)
}
}
// Visit exact match children first.
// Sort the child keys to generate deterministic sequence for better unit testing.
sort.Strings(exactMatchChildKeys)
for _, key := range exactMatchChildKeys {
if child, ok := hn.Children[key]; ok {
child.traverse(result)
}
}
// Visit vague match children after.
for _, child := range []*httpPatternTrieNode{singleParameterChild, singleWildCardChild, doubleWildCardChild} {
if child != nil {
child.traverse(result)
}
}
}
// If the current node is wildcard(**), its children has higher priority.
// For the wildcard case, it is necessary to traverse children then collect
// the current node.
// ex. /**/a
// /**
//
// For the non-wildcard, it is necessary to collect the current node then
// traver children.
// ex. /a
// /a/b
if hn.WildCard {
// Pre-order traverse.
traverseChildren()
// Post-order traverse.
appendMethodOnCurrentNode()
} else {
appendMethodOnCurrentNode()
traverseChildren()
}
}