-
Notifications
You must be signed in to change notification settings - Fork 11
Closed
Description
As it stands, it appears that only requests are validated by the Interceptor
implementation, i.e. when the client sends the request, when the handler receives the request. In the past, I've found it useful to also validate the response as a sanity check and to protect clients from an obviously broken implementation.
Would this be a feature you'd consider?
As a rough example of what I had in mind:
// WithValidateResponseFn configures a callback for response validation failures and enables response validation.
func WithValidateResponseFn(fn func(context.Context, error) error) Option {
return optionFunc(func(i *Interceptor) {
i.validateResponseFn = on
})
}
// (skip some code)
// WrapUnary implements connect.Interceptor.
func (i *Interceptor) WrapUnary(next connect.UnaryFunc) connect.UnaryFunc {
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
if err := validate(i.validator, req.Any()); err != nil {
return nil, err
}
resp, err := next(ctx, req)
if err != nil || i.validateResponseFn == nil {
return resp, err
}
if err := validate(i.validator, req.Any()); err != nil {
// user can choose to ignore the error, capture it for debugging, transform it into an internal error, etc.
if err := validateResponseFn(ctx, err); err != nil {
return nil, err
}
}
return resp, nil
}
}
// (similar code for the stream client/handler here)
// (example usage)
interceptor := validate.NewInterceptor(WithValidateResponseFn(func (ctx context.Context, err error) {
// log error for debugging
slog.ErrorContext(ctx, "response validation failed", slog.Any("error", err)
// record error on span
span := trace.SpanFromContext(ctx)
span.RecordError(err)
// transform the error to an internal error, hide the original from the client
connect.NewError(connect.CodeInternal, nil)
}))
// use interceptor here
_ = interceptor
Metadata
Metadata
Assignees
Labels
No labels