feat: add tag-based validation system with reflection caching
Implement a declarative struct tag validation system for Go: - Add validator.go with sync.Map caching for reflection metadata - Add rules.go with 11 built-in validation rules (required, email, pattern, honeypot, timing, etc.) - Add errors.go with FieldError and ValidationErrors types - Update ContactFormRequest with validate tags - Add ValidateContactFormV2() using the new tag-based validator Rules implemented: - required/optional: field presence validation - trim/sanitize: automatic value transformations - min/max: UTF-8 aware length validation - email: RFC 5322 email format validation - pattern: predefined regex patterns (name, subject, company) - no_injection: email header injection prevention - honeypot: bot trap (must be empty) - timing: timestamp validation for bot detection Documentation: - docs/go-validation-system.md: complete validation guide - docs/go-template-system.md: template manager documentation - docs/go-routes-api.md: routes and API reference - docs/README.md: documentation index
This commit is contained in:
@@ -11,13 +11,13 @@ import (
|
||||
|
||||
// ContactFormRequest represents a validated contact form submission
|
||||
type ContactFormRequest struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Company string `json:"company"`
|
||||
Subject string `json:"subject"`
|
||||
Message string `json:"message"`
|
||||
Honeypot string `json:"website"` // Should always be empty (bot trap)
|
||||
Timestamp int64 `json:"timestamp"` // Form load time (set by server)
|
||||
Name string `json:"name" validate:"required,trim,max=100,pattern=name,no_injection"`
|
||||
Email string `json:"email" validate:"required,trim,max=254,email,no_injection"`
|
||||
Company string `json:"company" validate:"optional,trim,max=100,pattern=company"`
|
||||
Subject string `json:"subject" validate:"required,trim,max=200,pattern=subject,no_injection"`
|
||||
Message string `json:"message" validate:"required,trim,max=5000,sanitize"`
|
||||
Honeypot string `json:"website" validate:"honeypot"` // Should always be empty (bot trap)
|
||||
Timestamp int64 `json:"timestamp" validate:"timing=2:86400"` // Form load time (set by server)
|
||||
}
|
||||
|
||||
// ValidationError represents a validation error with field context
|
||||
@@ -350,3 +350,12 @@ var (
|
||||
ErrFieldTooLong = errors.New("field exceeds maximum length")
|
||||
ErrSubmittedTooFast = errors.New("form submitted too quickly")
|
||||
)
|
||||
|
||||
// Global validator instance for reusing cached struct metadata
|
||||
var globalValidator = NewValidator()
|
||||
|
||||
// ValidateContactFormV2 validates a contact form using struct tags
|
||||
// This is the new validation method that uses the tag-based validator
|
||||
func ValidateContactFormV2(req *ContactFormRequest) error {
|
||||
return globalValidator.Validate(req)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user