-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidate.go
More file actions
82 lines (70 loc) · 2.92 KB
/
validate.go
File metadata and controls
82 lines (70 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package api
import (
"context"
"fmt"
"net/http"
)
// Validator is optionally implemented by request types to validate themselves
// after binding. Implementations that don't need the context can ignore it.
//
// Return api.ValidationErrors to have the framework route the failures through
// the configured ValidationErrorBuilder. Any other error type is forwarded to
// the router's ErrorHandler untouched.
type Validator interface {
Validate(ctx context.Context) error
}
// ValidatorFunc is the router-level validation plugin. It runs for every
// request after binding and per-type validation. Typical use is to wrap a
// reflection-based validator library:
//
// r := api.New(api.WithValidator(func(req any) error {
// return playground.New().Struct(req)
// }))
//
// Return api.ValidationErrors to get the configured builder; any other error
// is forwarded as-is.
type ValidatorFunc func(req any) error
// ValidationErrors is a collection of field-level validation failures.
// Any layer in the validation pipeline that returns this type (or wraps it
// via fmt.Errorf %w) is routed through the router's ValidationErrorBuilder.
type ValidationErrors []ValidationError
// Error implements the error interface.
func (v ValidationErrors) Error() string {
return fmt.Sprintf("%d validation error(s)", len(v))
}
// ValidationErrorBuilder shapes a slice of ValidationError into the response
// error returned to the router's ErrorHandler. Supply one via
// WithValidationErrorBuilder to unify validation errors with a domain error
// taxonomy.
type ValidationErrorBuilder interface {
Build(violations ValidationErrors) error
}
// ValidationMode controls when the constraint-tag checks run relative to the
// request type's Validator and the router-level ValidatorFunc.
type ValidationMode int
const (
// ValidateConstraintsLast runs the request's Validator, then the router's
// ValidatorFunc, then constraint-tag enforcement. The consumer's validator
// produces user-facing messages; tags act as a spec-fidelity backstop.
// This is the default.
ValidateConstraintsLast ValidationMode = iota
// ValidateConstraintsFirst runs constraint-tag enforcement first, failing
// fast on spec violations before any user validator runs.
ValidateConstraintsFirst
// ValidateConstraintsOff disables runtime enforcement of constraint tags.
// Tags still feed the OpenAPI spec; runtime validation is entirely owned
// by the consumer's Validator and ValidatorFunc.
ValidateConstraintsOff
)
// defaultValidationErrorBuilder builds a *ProblemDetail from a
// ValidationErrors slice. Used when no custom builder is configured.
type defaultValidationErrorBuilder struct{}
func (defaultValidationErrorBuilder) Build(violations ValidationErrors) error {
return &ProblemDetail{
Type: "about:blank",
Title: "Validation Failed",
Status: http.StatusBadRequest,
Detail: fmt.Sprintf("%d validation error(s)", len(violations)),
Errors: []ValidationError(violations),
}
}