Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

Codec architecture

Understand request, response, server, and stream codec ownership.

developer

The codec boundary is a typed composition of request encoding, response decoding, and optional stream handling. It owns wire semantics only. The transport owns HTTP status mapping, body limits, authorization, and the request context.

Ownership

type EncodedRequest struct {
	Header http.Header
	Body   io.Reader // consumed exactly once
}

type RequestEncoder interface {
	EncodeRequest(inference.Request, RequestMode) (EncodedRequest, error)
}

type ResponseDecoder interface {
	DecodeResponse([]byte) (*inference.Response, error)
}

type StreamDecoder interface {
	DecodeStream(*http.Response) (*stream.StreamReader[content.Chunk], error)
}

type Codec interface {
	RequestEncoder
	ResponseDecoder
}

Codec intentionally does not embed StreamDecoder, so a non-streaming API can satisfy the one-shot contract without a fake stream implementation. StreamingCodec adds the optional decoder. EncodedRequest.Body is single-use; the transport clears http.Request.GetBody and never retries it itself.

Stream lifetime

DecodeStream takes ownership of resp.Body. A successful return transfers close responsibility to the returned reader. If framing or decoder setup fails before a reader is returned, the decoder must close the body. The reader exposes chunks through Next, publishes terminal metadata only after clean io.EOF, and requires callers to call Close even after EOF.

%%{init: {"theme":"base","themeVariables":{"background":"#111827","primaryColor":"#1f2937","primaryTextColor":"#f9fafb","primaryBorderColor":"#60a5fa","lineColor":"#94a3b8","secondaryColor":"#172033","tertiaryColor":"#0f172a","fontFamily":"Inter, ui-sans-serif, system-ui"}}}%%
sequenceDiagram
    participant H as HTTP response
    participant C as Codec
    participant R as StreamReader
    H->>C: DecodeStream(resp)
    C->>R: frame and map body
    C-->>R: return reader
    R-->>C: Next() chunks
    R->>H: Close() owns body

Source and proof

Run go test ./codec/... ./stream/... ./transport/....

← back to documentation