From 6d8850654113fd075cf03e3ab58104c29f36de20 Mon Sep 17 00:00:00 2001 From: Patricio Whittingslow Date: Sun, 26 Jul 2026 11:54:51 -0300 Subject: [PATCH] add raw buffer access --- http/httphi/exchange.go | 12 ++++++++++++ http/httphi/router.go | 2 +- http/httpraw/header.go | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/http/httphi/exchange.go b/http/httphi/exchange.go index ff47e13..35bf8ee 100644 --- a/http/httphi/exchange.go +++ b/http/httphi/exchange.go @@ -119,6 +119,18 @@ func (exch *Exchange) Release() { exch.used.Store(false) } +// UnsafeRawBuffer returns the contiguous buffer being used for the request and response. +// Writing to it will mangle the entire request header+body and/or any staged response headers. +// Does not return the buffer used for the response first line so can be safely +// written to and used without modifying the staged response first line. +// +// Staging headers will write to this buffer so use mindfully. +// To access only the request header buffer portion use [httpraw.Header.BufferRaw] limited +// to [httpraw.Header.BufferParsed] as returned by [Exchange.RequestHeaderRaw]. +// +// In [Router] context, the size of this buffer is influenced directly by [RouterConfig] HeaderBufferSize fields. +func (exch *Exchange) UnsafeRawBuffer() []byte { return exch.rawbuf } + // StageHeader stages a response header field, written on the first // [Exchange.FlushHeader], [Exchange.WriteHeader] or [Exchange.Write]. // Returns false and drops the field if the response buffer cannot fit it. diff --git a/http/httphi/router.go b/http/httphi/router.go index 22ab30a..9ba1cbd 100644 --- a/http/httphi/router.go +++ b/http/httphi/router.go @@ -222,7 +222,7 @@ func (r *Router) awaitIdleExchangesLocked(maxWait time.Duration) error { // full, and an error when the router's goroutines have been torn down. On every // one of them conn is left untouched and unclosed for the caller to dispose of: // refusing connections is how a router with fixed memory applies backpressure. -func (r *Router) Handle(conn conn) error { +func (r *Router) Handle(conn io.ReadWriteCloser) error { // Exchange acquisition and the configuration it is served with must be read // under the same lock: [Router.Configure] may run concurrently. r.mu.Lock() diff --git a/http/httpraw/header.go b/http/httpraw/header.go index bc1e2e7..5dc345f 100644 --- a/http/httpraw/header.go +++ b/http/httpraw/header.go @@ -196,6 +196,10 @@ func (h *Header) BufferParsed() int { return h.hbuf.off } +// BufferRaw returns the undeerlying buffer as stored currently in memory. +// The length of the returned buffer is the used portion. Capacity of returned slice is [Header.BufferCapacity]. +func (h *Header) BufferRaw() []byte { return h.hbuf.buf } + // BufferUsed returns the raw memory used. // // BufferUsed + BufferFree == BufferCapacity