New test files: - config/config_test.go (100% coverage) - constants/constants_test.go (100% coverage) - httputil/response_test.go (100% coverage) - validation/rules_test.go (91.9% coverage) - middleware/logger_test.go, security_test.go, security_logger_test.go - handlers/errors_test.go Updated documentation: - doc/27-GO-TESTING.md: Complete testing guide - doc/00-GO-DOCUMENTATION-INDEX.md: Added testing section - doc/01-ARCHITECTURE.md: Updated package structure - doc/DECISIONS.md: Added ADR-004 caching decision - PROJECT-MEMORY.md: Added Go testing section
17 KiB
CV Site Go Documentation
Comprehensive documentation for the Go implementation of the CV site.
Documentation Overview
This documentation covers the core Go systems that power the CV site, with a focus on architecture, implementation details, and practical usage examples.
📚 Documentation Files
-
Go Validation System (739 lines)
- Tag-based validation with reflection caching
- Built-in validation rules (required, email, pattern, etc.)
- Security validation (injection prevention, honeypot, timing)
- Custom rule extension guide
- Complete ContactFormRequest example
-
Go Template System (894 lines)
- Thread-safe template manager
- Hot reload mechanism for development
- Custom template functions (iterate, eq, safeHTML, dict)
- Template organization and patterns
- Performance optimizations
-
Go Routes and API (1,203 lines)
- Complete route table with descriptions
- Middleware chain architecture
- Security features (CSP, HSTS, rate limiting)
- Protected endpoints and authentication
- API request/response formats
-
Go Testing (~450 lines)
- Coverage summary by package (100% for config, constants, httputil)
- Test file descriptions and locations
- Testing patterns (table-driven, HTTP handlers, middleware)
- Coverage gap explanations
- Best practices and CI/CD integration
Quick Navigation
By Feature
Validation:
Templates:
Routes:
Testing:
By Use Case
Setting Up Validation:
Creating Templates:
Adding Routes:
Writing Tests:
System Architecture
Overall Flow
┌──────────────────────────────────────────────────────────────┐
│ HTTP Request │
└──────────────────────┬───────────────────────────────────────┘
│
v
┌──────────────────────────────────────────────────────────────┐
│ Middleware Chain │
│ Recovery → Logger → SecurityHeaders → DynamicCache → │
│ Preferences → Router │
└──────────────────────┬───────────────────────────────────────┘
│
v
┌──────────────────────────────────────────────────────────────┐
│ Route Handler │
│ 1. Parse request │
│ 2. Get preferences from context │
│ 3. Load data (CV, config) │
│ 4. Validate input (if needed) │
│ 5. Render template │
└──────────────────────┬───────────────────────────────────────┘
│
v
┌──────────────────────────────────────────────────────────────┐
│ Template Rendering │
│ 1. Load template (hot reload in dev) │
│ 2. Execute with data │
│ 3. Apply custom functions │
│ 4. Output HTML │
└──────────────────────┬───────────────────────────────────────┘
│
v
┌──────────────────────────────────────────────────────────────┐
│ HTTP Response │
│ - Security headers │
│ - Cache headers │
│ - Content-Type │
│ - HTML/JSON/PDF body │
└──────────────────────────────────────────────────────────────┘
Contact Form Flow
POST /api/contact
│
v
┌─────────────────────┐
│ BrowserOnly │ Check User-Agent, Referer, Headers
│ Middleware │ → 403 if not browser
└─────────┬───────────┘
│
v
┌─────────────────────┐
│ RateLimiter │ 5 requests/hour per IP
│ (5/hour) │ → 429 if exceeded
└─────────┬───────────┘
│
v
┌─────────────────────┐
│ Parse JSON │ Decode ContactFormRequest
│ Request Body │
└─────────┬───────────┘
│
v
┌─────────────────────┐
│ Validate with │ Tag-based validation:
│ ValidateV2() │ - required, trim, max
│ │ - email, pattern
│ │ - no_injection, honeypot
│ │ - timing (2s-24h)
└─────────┬───────────┘
│
├─> Validation Failed → 400 + errors
│
v
┌─────────────────────┐
│ Send Email │ SMTP or email service
└─────────┬───────────┘
│
v
┌─────────────────────┐
│ 200 OK │ Success response
│ {success: true} │
└─────────────────────┘
Key Features
1. Validation System
Highlights:
- Reflection-based with
sync.Mapcaching for performance - Declarative tag syntax:
validate:"required,email,max=254" - 11+ built-in rules including security rules
- Extensible with custom rules
- Thread-safe concurrent validation
Performance:
- First validation: ~2000 ns/op
- Cached validations: ~1500 ns/op
- Pre-compiled regex patterns
Security:
- Email header injection prevention
- Honeypot bot detection
- Timing-based bot detection
- HTML sanitization
- UTF-8 aware length validation
2. Template System
Highlights:
- Thread-safe with
sync.RWMutex - Hot reload in development (edit without restart)
- 4 custom template functions
- Recursive partial loading
- Production caching
Custom Functions:
iterate(count)- Generate integer rangeseq(a, b)- String equalitysafeHTML(s)- Safe HTML (trusted content only)dict(k1, v1, ...)- Create maps for sub-templates
Thread Safety:
- Development: Full lock during reload
- Production: Read-only lock (concurrent)
3. Routes and Middleware
Highlights:
- 15+ routes (public, HTMX, API, protected)
- 8 middleware layers
- Comprehensive security headers
- Rate limiting (contact: 5/hour, PDF: 3/min)
- Origin checking for PDF exports
Security Features:
- Content Security Policy (CSP)
- HTTP Strict Transport Security (HSTS)
- BrowserOnly middleware (blocks curl/Postman)
- Email header injection prevention
- Rate limiting per IP
- Origin/Referer validation
Code Examples
Validation Example
// Define struct with validation tags
type ContactFormRequest struct {
Name string `json:"name" validate:"required,trim,max=100,pattern=name"`
Email string `json:"email" validate:"required,email,no_injection"`
Message string `json:"message" validate:"required,trim,max=5000,sanitize"`
}
// Validate
if err := validation.ValidateContactFormV2(req); err != nil {
// Handle validation errors
validationErrors := err.(validation.ValidationErrors)
return c.JSON(400, map[string]interface{}{
"errors": validationErrors,
})
}
Template Example
// Initialize template manager
cfg := &config.TemplateConfig{
Dir: "templates",
PartialsDir: "templates/partials",
HotReload: true, // Development
}
manager, _ := templates.NewManager(cfg)
// Render in handler
tmpl, _ := manager.Render("home.html")
tmpl.Execute(w, map[string]interface{}{
"Title": "CV",
"CV": cvData,
})
Route Example
// Protected contact endpoint
contactRateLimiter := middleware.NewRateLimiter(5, 1*time.Hour)
protectedHandler := middleware.BrowserOnly(
contactRateLimiter.Middleware(
http.HandlerFunc(cvHandler.HandleContact),
),
)
mux.Handle("/api/contact", protectedHandler)
Testing
Run All Tests
# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run specific package
go test ./internal/validation/...
# Run with verbose output
go test -v ./internal/routes/...
Test Examples
# Validation tests
go test ./internal/validation/ -v
# Template tests
go test ./internal/templates/ -v
# Middleware tests
go test ./internal/middleware/ -v
# Handler tests
go test ./internal/handlers/ -v
Performance
Benchmarks
# Run benchmarks
go test -bench=. ./...
# Validation benchmarks
go test -bench=Validate ./internal/validation/
# Template benchmarks
go test -bench=Render ./internal/templates/
Typical Performance
Validation:
- Contact form validation: ~1.5 µs
- Email validation: ~500 ns
- Pattern matching: ~300 ns (pre-compiled)
Templates:
- Template render (cached): ~50-100 µs
- Hot reload: ~1-2 ms (development only)
Routes:
- Middleware overhead: ~10-20 µs per request
- Rate limiter check: ~100-200 ns
- Total request latency: <5 ms (p50), <20 ms (p99)
Environment Configuration
Development
export GO_ENV=development
export TEMPLATE_HOT_RELOAD=true
export PORT=8080
Production
export GO_ENV=production
export TEMPLATE_HOT_RELOAD=false
export ALLOWED_ORIGINS="juan.andres.morenorub.io"
export PORT=8080
File Organization
cv/
├── doc/
│ ├── 24-GO-VALIDATION-SYSTEM.md # Validation docs
│ ├── 25-GO-TEMPLATE-SYSTEM.md # Template docs
│ ├── 26-GO-ROUTES-API.md # Routes/API docs
│ ├── 27-GO-TESTING.md # Testing & coverage
│ └── 00-GO-DOCUMENTATION-INDEX.md # This file
│
├── internal/
│ ├── validation/
│ │ ├── validator.go # Core validator
│ │ ├── rules.go # Validation rules
│ │ ├── errors.go # Error types
│ │ └── contact.go # ContactFormRequest
│ │
│ ├── templates/
│ │ └── template.go # Template manager
│ │
│ ├── routes/
│ │ └── routes.go # Route setup
│ │
│ ├── middleware/
│ │ ├── security.go # Security middleware
│ │ ├── browser_only.go # BrowserOnly middleware
│ │ ├── contact_rate_limit.go # Rate limiting
│ │ ├── logger.go # Request logging
│ │ ├── recovery.go # Panic recovery
│ │ └── preferences.go # User preferences
│ │
│ └── handlers/
│ ├── cv.go # CV handlers
│ ├── cv_contact.go # Contact handler
│ ├── cv_pdf.go # PDF handler
│ └── health.go # Health check
│
└── templates/
├── *.html # Main templates
└── partials/ # Partial templates
Best Practices
Validation
- Use tag-based validation for all struct validation
- Order rules correctly: transformations first (trim, sanitize), then validations
- Use global validator instance to benefit from caching
- Combine security rules for defense in depth
- UTF-8 aware: Use max/min for character count, not byte count
Templates
- Disable hot reload in production for performance
- Use safeHTML only with trusted content (YAML/config)
- Organize templates logically (main, partials, HTMX)
- Leverage custom functions for reusable logic
- Test template execution to catch errors early
Routes
- Register specific routes first to avoid conflicts
- Apply security middleware to sensitive endpoints
- Use rate limiting for resource-intensive operations
- Log all requests for monitoring
- Implement health checks for load balancers
Troubleshooting
Common Issues
Validation not working:
- Check tag syntax:
validate:"rule1,rule2=param" - Ensure field is exported (capitalized)
- Verify validator instance is created
Template not found:
- Check file exists in templates directory
- Verify filename matches
Render("name") - Check template loading logs
Rate limit too strict:
- Adjust limit in middleware initialization
- Clear rate limiter state (restart or implement clear endpoint)
CORS errors:
- Add domain to
ALLOWED_ORIGINSenvironment variable - Check
OriginCheckermiddleware configuration
Contributing
When adding new features:
- Update documentation in relevant .md file
- Add tests for new functionality
- Update route table if adding endpoints
- Document security implications if applicable
- Add examples for complex features
Version History
- v1.0 (2025-12-06) - Initial comprehensive documentation
- Validation system with tag-based approach
- Template system with hot reload
- Complete route and middleware documentation
License
This documentation is part of the CV site project.
Last Updated: December 6, 2025 Total Documentation: 3,300+ lines across 4 files Coverage: Validation, Templates, Routes, Middleware, Security, Testing