Files
go-omni/response/encoder.go
k2safe 7670b222ac feat: release configurable API response contracts
Define reusable response bodies in .api with typed code mappings, per-route overrides and matching OpenAPI schemas. Add application and callback encoders, early response policy selection, and isolated remote-consumer release verification.

Release v0.8.0-preview after full race, vet, build and local MySQL workflow acceptance.
2026-09-23 20:42:38 +08:00

61 lines
1.8 KiB
Go

package response
import (
"encoding/json"
"net/http"
)
// Result is the transport-independent input to an Encoder. Err is available for
// application error mapping; default encoders never expose it or its causes.
type Result struct {
Status int
Code, Message, RequestID string
Data any
Err error
}
// Payload is a complete response. Encoders must be safe for concurrent use.
// Status and headers are intentionally part of the contract: callback protocols
// may acknowledge an error using a different HTTP status or media type.
type Payload struct {
Status int
Header http.Header
Body []byte
}
type Encoder interface{ Encode(Result) (Payload, error) }
type EncoderFunc func(Result) (Payload, error)
func (f EncoderFunc) Encode(r Result) (Payload, error) { return f(r) }
func JSON(status int, value any) (Payload, error) {
data, err := json.Marshal(value)
if err != nil {
return Payload{}, err
}
return Payload{Status: status, Header: http.Header{"Content-Type": {"application/json; charset=utf-8"}}, Body: append(data, '\n')}, nil
}
func Text(status int, value string) Payload {
return Payload{Status: status, Header: http.Header{"Content-Type": {"text/plain; charset=utf-8"}}, Body: []byte(value)}
}
// Default is immutable; applications can use different encoders in one process.
var defaultEncoder = MustNew(Config{})
func Default() Encoder { return defaultEncoder }
// RawJSON leaves successful data unwrapped. Errors use the selected error
// policy; callback protocols with custom acknowledgments should use EncoderFunc.
func RawJSON(errors Encoder) Encoder {
if errors == nil {
errors = Default()
}
return EncoderFunc(func(r Result) (Payload, error) {
if r.Err != nil || r.Status >= 400 {
return errors.Encode(r)
}
return JSON(r.Status, r.Data)
})
}