MuxSlice more method muxing improvements

This commit is contained in:
Patricio Whittingslow
2026-07-29 23:58:59 -03:00
parent 2d68098537
commit be56c82b2c
8 changed files with 412 additions and 43 deletions
+22 -16
View File
@@ -70,32 +70,35 @@ type job struct {
}
// RouterConfig configures a [Router]. See [Router.Configure].
//
// Each field below opens with Required, Conditional or Optional followed by the
// constraint in brackets, that being what [RouterConfig.Validate] rejects on.
type RouterConfig struct {
// FixedNumGoroutines must be set to either -1 (freely allocate new goroutines) or to the number of goroutines
// to spawn on [Router.Configure] being called.
// Required [-1 or >0] number of goroutines to spawn on [Router.Configure],
// -1 meaning allocate them freely per connection instead.
FixedNumGoroutines int
// RequestHeaderBufferSize determines the buffer allocated
// for processing request HTTP headers including request-target (URI), protocol and key/value pairs.
// Required [>=32, sum with ResponseHeaderMinBufferSize <=65535] buffer for the
// request header: request-target (URI), protocol and key/value pairs.
RequestHeaderBufferSize int
// ResponseHeaderMinBufferSize determines buffer allocated for processing response headers.
// Response buffer will reuse unused request memory so this is not a strict limit.
// "HTTP/1.1 200 OK\r\n" does not count towards this memory, only actual Headers key/value pairs use this memory.
// After memory is fully consumed [Exchange.StageHeader] will not append more headers.
// Required [>=2, <=65535] buffer for response headers. Reuses unused request
// memory so it is not a strict limit, and the status line does not count
// towards it. Once consumed [Exchange.StageHeader] appends no more fields.
ResponseHeaderMinBufferSize int
// Number of request header key/value pairs to parse before failing and returning [StatusRequestHeaderFieldsTooLarge].
// Required [>0] request header key/value pairs to parse before failing with
// [StatusRequestHeaderFieldsTooLarge].
RequestNumHeaderKVCap int
// NormalizeOutgoingKeys normalizes response header field keys as they are
// Optional [any] normalization of response header field keys as they are
// staged, i.e: "content-type" becomes "Content-Type".
NormalizeOutgoingKeys bool
// MaxAwaitingConns is the depth of the queue connections wait in for a free
// goroutine. [Router.Handle] drops connections once it is full. Required and
// must be non-zero when running a fixed number of goroutines, unused otherwise.
// Conditional [>0 when FixedNumGoroutines>0, unused otherwise] depth of the
// queue connections wait in. [Router.Handle] drops connections once it is full.
MaxAwaitingConns int
// Mux resolves each request's method and path to the handler serving it. Required.
// Required [non-nil] resolver of each request's method and path to the handler
// serving it. Routes must be registered before Configure, see [Mux.MaxPathValues].
Mux Mux
// Logger receives failed exchanges. Optional, nil disables logging.
// Optional [nil disables] sink for failed exchanges.
Logger *slog.Logger
}
@@ -185,6 +188,9 @@ func (r *Router) Configure(cfg RouterConfig) error {
r.mux = cfg.Mux
r.log = cfg.Logger
maxPathValues := cfg.Mux.MaxPathValues()
if maxPathValues < 0 {
return errors.New("Mux paths must be registered before configuring Router")
}
r.maxPathValues = maxPathValues
r.normalizeKeys = cfg.NormalizeOutgoingKeys
// Freelist entries were sized by the outgoing configuration: recycling one
@@ -306,7 +312,7 @@ func (r *Router) goroWorker(gen uint32, queue chan job, mux Mux) {
for job := range queue {
exch := job.exch
if exch == nil {
panic("httplo: unreachable nil job")
panic("httphi: unreachable nil job")
} else if gen != r.gen.Load() {
// Not released with freeExch since generation torn down,
// new buffer may have been allocated for Exchanges.