Improve error messages
diff --git a/router.go b/router.go
index 5172c89..155b871 100644
--- a/router.go
+++ b/router.go
@@ -213,7 +213,7 @@
// communication with a proxy).
func (r *Router) Handle(method, path string, handle Handle) {
if path[0] != '/' {
- panic("path must begin with '/'")
+ panic("path must begin with '/' in path '" + path + "'")
}
if r.trees == nil {
@@ -257,7 +257,7 @@
// router.ServeFiles("/src/*filepath", http.Dir("/var/www"))
func (r *Router) ServeFiles(path string, root http.FileSystem) {
if len(path) < 10 || path[len(path)-10:] != "/*filepath" {
- panic("path must end with /*filepath")
+ panic("path must end with /*filepath in path '" + path + "'")
}
fileServer := http.FileServer(root)
diff --git a/tree.go b/tree.go
index b741654..a15bc2c 100644
--- a/tree.go
+++ b/tree.go
@@ -7,7 +7,6 @@
import (
"strings"
"unicode"
- "fmt"
)
func min(a, b int) int {
@@ -79,6 +78,7 @@
// addRoute adds a node with the given handle to the path.
// Not concurrency-safe!
func (n *node) addRoute(path string, handle Handle) {
+ fullPath := path
n.priority++
numParams := countParams(path)
@@ -148,7 +148,9 @@
}
}
- panic(fmt.Sprintf("conflict with wildcard route. has %q got %q", path, n.path))
+ panic("path segment '" + path +
+ "' conflicts with existing wildcard '" + n.path +
+ "' in path '" + fullPath + "'")
}
c := path[0]
@@ -180,23 +182,23 @@
n.incrementChildPrio(len(n.indices) - 1)
n = child
}
- n.insertChild(numParams, path, handle)
+ n.insertChild(numParams, path, fullPath, handle)
return
} else if i == len(path) { // Make node a (in-path) leaf
if n.handle != nil {
- panic(fmt.Sprintf("a Handle is already registered for this path (%q)", path))
+ panic("a handle is already registered for path ''" + fullPath + "'")
}
n.handle = handle
}
return
}
} else { // Empty tree
- n.insertChild(numParams, path, handle)
+ n.insertChild(numParams, path, fullPath, handle)
}
}
-func (n *node) insertChild(numParams uint8, path string, handle Handle) {
+func (n *node) insertChild(numParams uint8, path, fullPath string, handle Handle) {
var offset int // already handled bytes of the path
// find prefix until first wildcard (beginning with ':'' or '*'')
@@ -206,27 +208,29 @@
continue
}
- // check if this Node existing children which would be
- // unreachable if we insert the wildcard here
- if len(n.children) > 0 {
- panic("wildcard route conflicts with existing children")
- }
-
// find wildcard end (either '/' or path end)
end := i + 1
for end < max && path[end] != '/' {
switch path[end] {
// the wildcard name must not contain ':' and '*'
case ':', '*':
- panic("only one wildcard per path segment is allowed")
+ panic("only one wildcard per path segment is allowed, has: '" +
+ path[i:] + "' in path '" + fullPath + "'")
default:
end++
}
}
+ // check if this Node existing children which would be
+ // unreachable if we insert the wildcard here
+ if len(n.children) > 0 {
+ panic("wildcard route '" + path[i:end] +
+ "' conflicts with existing children in path '" + fullPath + "'")
+ }
+
// check if the wildcard has a name
if end-i < 2 {
- panic("wildcards must be named with a non-empty name")
+ panic("wildcards must be named with a non-empty name in path '" + fullPath + "'")
}
if c == ':' { // param
@@ -262,17 +266,17 @@
} else { // catchAll
if end != max || numParams > 1 {
- panic("catch-all routes are only allowed at the end of the path")
+ panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'")
}
if len(n.path) > 0 && n.path[len(n.path)-1] == '/' {
- panic("catch-all conflicts with existing handle for the path segment root")
+ panic("catch-all conflicts with existing handle for the path segment root in path '" + fullPath + "'")
}
// currently fixed width 1 for '/'
i--
if path[i] != '/' {
- panic("no / before catch-all")
+ panic("no / before catch-all in path '" + fullPath + "'")
}
n.path = path[offset:i]
@@ -397,7 +401,7 @@
return
default:
- panic("Invalid node type")
+ panic("invalid node type")
}
}
} else if path == n.path {
@@ -508,7 +512,7 @@
return append(ciPath, path...), true
default:
- panic("Invalid node type")
+ panic("invalid node type")
}
} else {
// We should have reached the node containing the handle.
diff --git a/tree_test.go b/tree_test.go
index 262681b..64f26d1 100644
--- a/tree_test.go
+++ b/tree_test.go
@@ -358,7 +358,7 @@
tree.addRoute(route, nil)
})
- if rs, ok := recv.(string); !ok || rs != panicMsg {
+ if rs, ok := recv.(string); !ok || !strings.HasPrefix(rs, panicMsg) {
t.Fatalf(`"Expected panic "%s" for route '%s', got "%v"`, panicMsg, route, recv)
}
}
@@ -584,6 +584,8 @@
}
func TestTreeInvalidNodeType(t *testing.T) {
+ const panicMsg = "invalid node type"
+
tree := &node{}
tree.addRoute("/", fakeHandler("/"))
tree.addRoute("/:page", fakeHandler("/:page"))
@@ -595,15 +597,15 @@
recv := catchPanic(func() {
tree.getValue("/test")
})
- if rs, ok := recv.(string); !ok || rs != "Invalid node type" {
- t.Fatalf(`Expected panic "Invalid node type", got "%v"`, recv)
+ if rs, ok := recv.(string); !ok || rs != panicMsg {
+ t.Fatalf("Expected panic '"+panicMsg+"', got '%v'", recv)
}
// case-insensitive lookup
recv = catchPanic(func() {
tree.findCaseInsensitivePath("/test", true)
})
- if rs, ok := recv.(string); !ok || rs != "Invalid node type" {
- t.Fatalf(`Expected panic "Invalid node type", got "%v"`, recv)
+ if rs, ok := recv.(string); !ok || rs != panicMsg {
+ t.Fatalf("Expected panic '"+panicMsg+"', got '%v'", recv)
}
}