diff --git a/contrib/codecs/http/codec.go b/contrib/codecs/http/codec.go
index 8d91865921d7851f88a1e2c021031ebdb984f9f9..fee62d2565437c32f69696158c04c331d5d11d1d 100644
--- a/contrib/codecs/http/codec.go
+++ b/contrib/codecs/http/codec.go
@@ -105,7 +105,7 @@ func (r *Codec) doReadRPC() (msgs json.RawMessage, err error) {
 	if err != nil {
 		return nil, err
 	}
-	req := codec.NewRequest(r.ctx, id, method_up, data)
+	req := codec.NewRequest(r.ctx, id, method_up, json.RawMessage(data))
 	return req.MarshalJSON()
 }
 
diff --git a/contrib/jmux/mux.go b/contrib/jmux/mux.go
index 3a9f71ca9c1f98fb87ddfeebd686ec6c870f3928..14c214b54f1588f040e154aace01755ae794bf63 100644
--- a/contrib/jmux/mux.go
+++ b/contrib/jmux/mux.go
@@ -5,6 +5,7 @@ import (
 	"errors"
 	"fmt"
 	"reflect"
+	"strings"
 	"sync"
 
 	"gfx.cafe/open/jrpc/contrib/handlers/argreflect"
@@ -344,6 +345,10 @@ func (mx *Mux) handle(pattern string, handler codec.Handler) *node {
 		panic(fmt.Sprintf("rpc: routing pattern must not be empty in '%s'", pattern))
 	}
 
+	if !strings.HasPrefix(pattern, "/") {
+		pattern = "/" + pattern
+	}
+
 	// Build the computed routing handler for this routing pattern.
 	if !mx.inline && mx.handler == nil {
 		mx.updateRouteHandler()
@@ -362,7 +367,7 @@ func (mx *Mux) handle(pattern string, handler codec.Handler) *node {
 	return mx.tree.InsertRoute(pattern, h)
 }
 
-// routeJRPC routes a Request through the Mux routing tree to serve
+// routeRPC routes a Request through the Mux routing tree to serve
 // the matching handler for a particular jrpc method.
 func (mx *Mux) routeRPC(w codec.ResponseWriter, r *codec.Request) {
 	// Grab the route context object
@@ -392,10 +397,10 @@ func (mx *Mux) routeRPC(w codec.ResponseWriter, r *codec.Request) {
 }
 
 func (mx *Mux) nextRoutePath(rctx *Context) string {
-	routePath := ""
+	routePath := sepString
 	nx := len(rctx.routeParams.Keys) - 1 // index of last param in list
 	if nx >= 0 && rctx.routeParams.Keys[nx] == "*" && len(rctx.routeParams.Values) > nx {
-		routePath = rctx.routeParams.Values[nx]
+		routePath = sepString + rctx.routeParams.Values[nx]
 	}
 	return routePath
 }
diff --git a/contrib/jmux/router_tree.go b/contrib/jmux/router_tree.go
index b9e9e4207aa11520574f78f5fbfd988a20f73898..1c34031d086d902f78e4087b577ee2268e612624 100644
--- a/contrib/jmux/router_tree.go
+++ b/contrib/jmux/router_tree.go
@@ -5,10 +5,11 @@ package jmux
 
 import (
 	"fmt"
-	"gfx.cafe/open/jrpc/pkg/codec"
 	"regexp"
 	"sort"
 	"strings"
+
+	"gfx.cafe/open/jrpc/pkg/codec"
 )
 
 type nodeTyp uint8
@@ -277,6 +278,10 @@ func (n *node) FindRoute(rctx *Context, path string) (*node, *endpoint, codec.Ha
 	rctx.routeParams.Keys = rctx.routeParams.Keys[:0]
 	rctx.routeParams.Values = rctx.routeParams.Values[:0]
 
+	if !strings.HasPrefix(path, "/") {
+		path = "/" + path
+	}
+
 	// Find the routing handlers for the path
 	rn := n.findRoute(rctx, path)
 	if rn == nil {
@@ -338,7 +343,7 @@ func (n *node) findRoute(rctx *Context, path string) *node {
 				p := strings.IndexByte(xsearch, xn.tail)
 
 				if p < 0 {
-					if xn.tail == '_' {
+					if xn.tail == sepRune {
 						p = len(xsearch)
 					} else {
 						continue
@@ -351,7 +356,7 @@ func (n *node) findRoute(rctx *Context, path string) *node {
 					if !xn.rex.MatchString(xsearch[:p]) {
 						continue
 					}
-				} else if strings.IndexByte(xsearch[:p], '_') != -1 {
+				} else if strings.IndexByte(xsearch[:p], sepRune) != -1 {
 					// avoid a match across path segments
 					continue
 				}