diff --git a/contrib/codecs/http/client.go b/contrib/codecs/http/client.go
index 95fb6f169bfe8a4bdb4969c6f4832c2bfc39236c..9000516a6f3563068784df0a5a0552dd5c8d63d0 100644
--- a/contrib/codecs/http/client.go
+++ b/contrib/codecs/http/client.go
@@ -3,15 +3,18 @@ package http
 import (
 	"bytes"
 	"context"
+	"crypto/tls"
 	"encoding/json"
 	"errors"
 	"fmt"
 	"io"
+	"net"
 	"net/http"
 	"sync"
 	"sync/atomic"
 
 	"gfx.cafe/open/jrpc/pkg/jsonrpc"
+	"golang.org/x/net/http2"
 
 	"gfx.cafe/util/go/bufpool"
 
@@ -26,6 +29,18 @@ var (
 	errDead                      = errors.New("connection lost")
 )
 
+var DefaultH2CClient = &http.Client{
+	Transport: &http2.Transport{
+		// So http2.Transport doesn't complain the URL scheme isn't 'https'
+		AllowHTTP: true,
+		// Pretend we are dialing a TLS endpoint. (Note, we ignore the passed tls.Config)
+		DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
+			var d net.Dialer
+			return d.DialContext(ctx, network, addr)
+		},
+	},
+}
+
 var _ jsonrpc.Conn = (*Client)(nil)
 
 // Client represents a connection to an RPC server.
@@ -54,7 +69,9 @@ func (c *Client) Mount(h jsonrpc.Middleware) {
 func DialHTTP(target string) (*Client, error) {
 	return Dial(nil, http.DefaultClient, target)
 }
-
+func DialH2C(target string) (*Client, error) {
+	return Dial(nil, DefaultH2CClient, target)
+}
 func Dial(ctx context.Context, client *http.Client, target string) (*Client, error) {
 	if client == nil {
 		client = http.DefaultClient
diff --git a/contrib/codecs/http/testing.go b/contrib/codecs/http/testing.go
index aa708c7eda0873b007fb732eb1eb93e4cc3247ab..27df7c49495ecd9767c5510ad863d1ec1a88994e 100644
--- a/contrib/codecs/http/testing.go
+++ b/contrib/codecs/http/testing.go
@@ -10,7 +10,7 @@ import (
 
 func ServerMaker() (*server.Server, jrpctest.ClientMaker, func()) {
 	s := jrpctest.NewServer()
-	hsrv := httptest.NewServer(&Server{Server: s})
+	hsrv := httptest.NewServer(HttpHandler(s))
 	return s, func() jsonrpc.Conn {
 		conn, err := DialHTTP(hsrv.URL)
 		if err != nil {
diff --git a/contrib/codecs/init.go b/contrib/codecs/init.go
index 6b6658cdc606b03a8f3044454063882607f04d75..357c25960685f24689de30b6b14db0572c10f433 100644
--- a/contrib/codecs/init.go
+++ b/contrib/codecs/init.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"net"
 	"net/url"
+	"strings"
 
 	gohttp "net/http"
 
@@ -45,10 +46,9 @@ func init() {
 			go rdwr.NewCodec(conn, conn)
 		}
 	}, "tcp")
-
-	RegisterHandler(func(bind *url.URL, srv *server.Server, opts map[string]any) error {
-		return gohttp.ListenAndServe(bind.Host, HttpHandler(srv))
-	}, "http")
+	RegisterDialer(func(ctx context.Context, url string) (jsonrpc.Conn, error) {
+		return http.Dial(ctx, http.DefaultH2CClient, strings.Replace(url, "h2c", "http", 1))
+	}, "h2c")
 	RegisterDialer(func(ctx context.Context, url string) (jsonrpc.Conn, error) {
 		return http.Dial(ctx, nil, url)
 	}, "https", "http")