h1

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 19, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package h1 implements a zero-copy HTTP/1.1 parser.

This is a low-level parser package consumed by the celeris engine layer (engine/iouring, engine/epoll, engine/std bridge); application code should not import it directly. The parser returns header and body slices that alias the connection's read buffer — callers must materialize (clone) any value they retain past the next [ParseRequest] call on the same connection.

Index

Constants

View Source
const MaxHeaderCount = 200

MaxHeaderCount caps the number of header fields in a single request. Prevents an attacker from sending thousands of tiny headers that stay under the MaxHeaderSize byte limit while still triggering O(n) slice growth and scan work. 200 sits above typical nginx/apache defaults (100 for client headers, but verbose proxy chains can add more) and well below the thousands-per-request attack threshold.

View Source
const MaxHeaderSize = 64 << 10

MaxHeaderSize is the maximum allowed size of HTTP headers in bytes. 64 KiB matches nginx's large_client_header_buffers ceiling and is two orders of magnitude below the previous 16 MiB which was a slow-loris amplifier. Legitimate request headers are always well under a few KiB; 64 KiB accommodates edge cases like verbose proxy chains without exposing the server to per-connection memory exhaustion.

Variables

View Source
var (
	ErrBufferExhausted        = errors.New("buffer exhausted")
	ErrInvalidRequestLine     = errors.New("invalid request line")
	ErrInvalidHeader          = errors.New("invalid header line")
	ErrMissingHost            = errors.New("missing Host header")
	ErrUnsupportedVersion     = errors.New("unsupported HTTP version")
	ErrHeadersTooLarge        = errors.New("headers too large")
	ErrTooManyHeaders         = errors.New("too many headers")
	ErrInvalidContentLength   = errors.New("invalid content-length")
	ErrDuplicateContentLength = errors.New("duplicate content-length with conflicting values")
)

H1 parser sentinel errors.

Functions

func LowerHeaderCopy added in v1.4.0

func LowerHeaderCopy(raw []byte) string

LowerHeaderCopy returns a pre-allocated lowercase string for common HTTP header names, falling back to strings.ToLower(string(raw)) for uncommon names. Unlike UnsafeLowerHeader, the returned string never aliases raw — safe to retain after raw's backing buffer is reused.

func LowerInPlace added in v1.1.0

func LowerInPlace(b []byte)

LowerInPlace lowercases ASCII bytes in-place.

func UnsafeLowerHeader added in v1.1.0

func UnsafeLowerHeader(raw []byte) string

UnsafeLowerHeader returns an interned string for common HTTP header names, or lowercases the name in-place and returns a zero-copy unsafe string. The caller must ensure the byte slice outlives the returned string.

func UnsafeString added in v1.1.0

func UnsafeString(b []byte) string

UnsafeString returns a string that shares the underlying byte slice memory. The caller must ensure the byte slice is not modified while the string is in use.

Types

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

Parser is a zero-allocation HTTP/1.x request parser.

func NewParser

func NewParser() *Parser

NewParser returns a new Parser ready for use.

func (*Parser) ConsumeBody

func (p *Parser) ConsumeBody(n int)

ConsumeBody advances the parser position by n bytes.

func (*Parser) GetBody

func (p *Parser) GetBody(contentLength int64) []byte

GetBody returns a zero-copy slice of the request body for the given content length.

func (*Parser) ParseChunkedBody

func (p *Parser) ParseChunkedBody() ([]byte, int, error)

ParseChunkedBody parses a single chunk from chunked transfer encoding. Returns a zero-copy slice into the parser buffer, bytes consumed, or error. Returns (nil, 0, nil) when more data is needed.

func (*Parser) ParseRequest

func (p *Parser) ParseRequest(req *Request) (int, error)

ParseRequest parses a complete HTTP/1.x request from the buffer into req.

func (*Parser) Remaining

func (p *Parser) Remaining() int

Remaining returns the number of unconsumed bytes in the buffer.

func (*Parser) Reset

func (p *Parser) Reset(buf []byte)

Reset reinitializes the parser with a new input buffer.

func (*Parser) SetZeroCopy added in v1.1.0

func (p *Parser) SetZeroCopy(enabled bool)

SetZeroCopy enables zero-copy header parsing. When enabled, the parser only populates RawHeaders (not Headers). The caller must convert RawHeaders to strings — typically via unsafe.String for zero allocation.

type Request

type Request struct {
	Method          string
	Path            string
	Version         string
	Headers         [][2]string
	RawHeaders      [][2][]byte
	Host            string
	ContentLength   int64
	ChunkedEncoding bool
	KeepAlive       bool
	HeadersComplete bool
	BodyRead        int64
	ExpectContinue  bool

	// UpgradeH2C is true iff this request is a valid h2c upgrade request
	// (RFC 7540 §3.2): Upgrade: h2c (single token, exclusively) + HTTP2-Settings
	// header present + Connection header listing BOTH "upgrade" and
	// "http2-settings" tokens. The single-token Upgrade requirement
	// disambiguates from the WebSocket path (Upgrade: websocket).
	UpgradeH2C bool
	// HTTP2Settings holds the raw base64url-encoded HTTP2-Settings value
	// (still encoded; caller decodes). Non-empty only when the header is present.
	HTTP2Settings string
}

Request holds the parsed components of an HTTP/1.x request.

func (*Request) Reset

func (r *Request) Reset()

Reset clears all fields, reusing existing header slice capacity.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL