diff --git a/handler.go b/handler.go
index cb41d69a40863c8ffe09f6dabd1a25e30c4f8031..2a69ba8081bcaf4aa83d8828d0331391ec760e2b 100644
--- a/handler.go
+++ b/handler.go
@@ -226,6 +226,7 @@ func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage
 	}
 	req := &Request{ctx: cp.ctx, msg: *msg, peer: h.peer}
 	mw := NewReaderResponseWriterMsg(req)
+	// now actually run the handler
 	h.reg.ServeRPC(mw, req)
 
 	//TODO: notifications
diff --git a/http.go b/http.go
index 553de3d3e72131a68f63f6897a9beaafc79aa283..6f9475b2549b310e15aa64c77b566c135f30c397 100644
--- a/http.go
+++ b/http.go
@@ -30,6 +30,8 @@ import (
 	"strings"
 	"sync"
 	"time"
+
+	"gfx.cafe/util/go/bufpool"
 )
 
 const (
@@ -219,7 +221,11 @@ func (hc *httpConn) doRequest(ctx context.Context, msg any) (io.ReadCloser, erro
 type httpServerConn struct {
 	io.Reader
 	io.Writer
+
+	jc ServerCodec
+
 	r *http.Request
+	w http.ResponseWriter
 }
 
 func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec {
@@ -240,8 +246,8 @@ func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec {
 		if pb, err := base64.URLEncoding.DecodeString(params); err == nil {
 			param = pb
 		}
-		buf := new(bytes.Buffer)
-		buf.Grow(128)
+		buf := bufpool.GetStd()
+		defer bufpool.Put(buf)
 		jzon.NewEncoder(buf).Encode(jsonrpcMessage{
 			ID:     NewStringIDPtr(id),
 			Method: method_up,
@@ -252,7 +258,54 @@ func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec {
 		// it's a post request or whatever, so just process it like normal
 		conn.Reader = io.LimitReader(r.Body, maxRequestContentLength)
 	}
-	return NewCodec(conn)
+	conn.jc = NewCodec(conn)
+	return conn
+}
+
+func (c *httpServerConn) peerInfo() PeerInfo {
+	connInfo := PeerInfo{
+		Transport:  "http",
+		RemoteAddr: c.remoteAddr(),
+		HTTP: HttpInfo{
+			Version:      c.r.Proto,
+			UserAgent:    c.r.UserAgent(),
+			Origin:       c.r.Header.Get("Origin"),
+			Host:         c.r.Host,
+			Headers:      c.r.Header,
+			WriteHeaders: c.w.Header(),
+		},
+	}
+
+	connInfo.HTTP.Origin = c.r.Header.Get("X-Real-Ip")
+	if connInfo.HTTP.Origin == "" {
+		connInfo.HTTP.Origin = c.r.Header.Get("X-Forwarded-For")
+	}
+	if connInfo.HTTP.Origin == "" {
+		connInfo.HTTP.Origin = c.r.Header.Get("Origin")
+	}
+
+	return connInfo
+}
+
+func (c *httpServerConn) remoteAddr() string {
+	return c.RemoteAddr()
+}
+
+func (c *httpServerConn) readBatch() (messages []*jsonrpcMessage, batch bool, err error) {
+	return c.jc.readBatch()
+}
+
+func (c *httpServerConn) writeJSON(ctx context.Context, v any) error {
+	return c.jc.writeJSON(ctx, v)
+}
+
+func (c *httpServerConn) close() {
+	c.jc.close()
+}
+
+// Closed returns a channel which will be closed when Close is called
+func (c *httpServerConn) closed() <-chan any {
+	return c.jc.closed()
 }
 
 // Close does nothing and always returns nil.
diff --git a/protocol.go b/protocol.go
index 808023610350fae550837694fb6991f61b01f195..42c89e1ea4285e3531796048835782c4ece2639e 100644
--- a/protocol.go
+++ b/protocol.go
@@ -3,6 +3,7 @@ package jrpc
 import (
 	"context"
 	"encoding/json"
+	"net/http"
 )
 
 type HandlerFunc func(w ResponseWriter, r *Request)
@@ -14,6 +15,7 @@ type Handler interface {
 type ResponseWriter interface {
 	Send(v any, err error) error
 	Notify(v any) error
+	Header() http.Header
 }
 
 func (fn HandlerFunc) ServeRPC(w ResponseWriter, r *Request) {
@@ -118,6 +120,10 @@ func NewReaderResponseWriterMsg(r *Request) *ResponseWriterMsg {
 	return rw
 }
 
+func (w *ResponseWriterMsg) Header() http.Header {
+	return w.r.Peer().HTTP.WriteHeaders
+}
+
 func (w *ResponseWriterMsg) Send(args any, e error) (err error) {
 	cm := w.r.Msg()
 	if e != nil {
diff --git a/server.go b/server.go
index 8a8247db622e6f16e9461329232446623ee11a45..ab37347a33578dcd1bff28247f6cb5a33becc453 100644
--- a/server.go
+++ b/server.go
@@ -135,16 +135,20 @@ type PeerInfo struct {
 	RemoteAddr string
 
 	// Addditional information for HTTP and WebSocket connections.
-	HTTP struct {
-		// Protocol version, i.e. "HTTP/1.1". This is not set for WebSocket.
-		Version string
-		// Header values sent by the client.
-		UserAgent string
-		Origin    string
-		Host      string
-
-		Headers http.Header
-	}
+	HTTP HttpInfo
+}
+
+type HttpInfo struct {
+	// Protocol version, i.e. "HTTP/1.1". This is not set for WebSocket.
+	Version string
+	// Header values sent by the client.
+	UserAgent string
+	Origin    string
+	Host      string
+
+	Headers http.Header
+
+	WriteHeaders http.Header
 }
 
 type peerInfoContextKey struct{}