feat: release v0.26 portable i18n and presentation adapters
This commit is contained in:
@@ -88,15 +88,16 @@ func RoutePattern(ctx context.Context) string {
|
||||
// only standard-library HTTP types, so it remains usable when the network
|
||||
// implementation is replaced.
|
||||
type Context struct {
|
||||
request *http.Request
|
||||
writer http.ResponseWriter
|
||||
params map[string]string
|
||||
values map[string]any
|
||||
responded bool
|
||||
status int
|
||||
encoder response.Encoder
|
||||
errorRegistry *apierrors.Registry
|
||||
failure *apierrors.APIError
|
||||
request *http.Request
|
||||
writer http.ResponseWriter
|
||||
params map[string]string
|
||||
values map[string]any
|
||||
responded bool
|
||||
status int
|
||||
encoder response.Encoder
|
||||
errorRegistry *apierrors.Registry
|
||||
errorLocalizer apierrors.Localizer
|
||||
failure *apierrors.APIError
|
||||
}
|
||||
|
||||
// NewContext creates a transport-neutral GoOmni context.
|
||||
@@ -136,6 +137,7 @@ func (c *Context) Clone(ctx context.Context, writer http.ResponseWriter) *Contex
|
||||
clone := NewContext(c.request.Clone(ctx), writer, c.params)
|
||||
clone.encoder = c.encoder
|
||||
clone.errorRegistry = c.errorRegistry
|
||||
clone.errorLocalizer = c.errorLocalizer
|
||||
for key, value := range c.values {
|
||||
clone.values[key] = value
|
||||
}
|
||||
@@ -301,16 +303,20 @@ func (c *Context) WriteError(err error) {
|
||||
// SetErrorRegistry sets an application fallback. Route encoders can supply their
|
||||
// own nonempty registry; an encoder without a registry inherits this fallback.
|
||||
// Clones retain both policies without any process-global lookup.
|
||||
func (c *Context) SetErrorRegistry(r *apierrors.Registry) { c.errorRegistry = r }
|
||||
func (c *Context) ResolveError(err error) *apierrors.APIError {
|
||||
func (c *Context) SetErrorRegistry(r *apierrors.Registry) { c.errorRegistry = r }
|
||||
func (c *Context) SetErrorLocalizer(l apierrors.Localizer) { c.errorLocalizer = l }
|
||||
|
||||
// ErrorRegistry returns the effective route or application error scope.
|
||||
func (c *Context) ErrorRegistry() *apierrors.Registry {
|
||||
registry := c.errorRegistry
|
||||
if provider, ok := c.encoder.(response.ErrorRegistryProvider); ok {
|
||||
if scoped := provider.ErrorRegistry(); scoped != nil {
|
||||
registry = scoped
|
||||
}
|
||||
}
|
||||
return registry.Resolve(err)
|
||||
return registry
|
||||
}
|
||||
func (c *Context) ResolveError(err error) *apierrors.APIError { return c.ErrorRegistry().Resolve(err) }
|
||||
|
||||
// RecordError preserves failure semantics when a middleware commits buffered bytes.
|
||||
func (c *Context) RecordError(err error) { c.failure = c.ResolveError(err) }
|
||||
|
||||
@@ -53,6 +53,15 @@ func (c *Context) writeResult(result response.Result) (err error) {
|
||||
if encoder == nil {
|
||||
encoder = response.Default()
|
||||
}
|
||||
if c.errorLocalizer != nil && result.Err != nil {
|
||||
if message, ok := c.localizedMessage(result.Err); ok {
|
||||
result.MessageOverride = &message
|
||||
if c.failure != nil {
|
||||
c.failure = c.failure.Clone()
|
||||
c.failure.Message = message
|
||||
}
|
||||
}
|
||||
}
|
||||
payload, err := encoder.Encode(result)
|
||||
if err != nil {
|
||||
return apierrors.Internal(err)
|
||||
@@ -69,6 +78,17 @@ func (c *Context) writeResult(result response.Result) (err error) {
|
||||
return c.WriteResponse(payload.Status, payload.Header, payload.Body)
|
||||
}
|
||||
|
||||
// Presentation adapter failures cannot turn a business result into a new error.
|
||||
func (c *Context) localizedMessage(err error) (message string, ok bool) {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
message, ok = "", false
|
||||
}
|
||||
}()
|
||||
registry := c.ErrorRegistry()
|
||||
return c.errorLocalizer.Localize(c.Context(), registry, registry.Resolve(err))
|
||||
}
|
||||
|
||||
// RespondStatus uses the current response format and error catalog, but keeps
|
||||
// the explicit HTTP status even if a catalog/custom encoder selects another.
|
||||
// This is useful for protocol endpoints such as health probes. Ordinary
|
||||
|
||||
Reference in New Issue
Block a user