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.
61 lines
1.8 KiB
Go
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)
|
|
})
|
|
}
|