package handlers import ( "fmt" "net/http" ) // ============================================================================== // REQUEST/RESPONSE TYPES // Structured types for common request patterns with validation // ============================================================================== // LanguageRequest represents a request with language parameter type LanguageRequest struct { Lang string `validate:"required,oneof=en es"` } // ParseLanguageRequest parses and validates language from query parameters func ParseLanguageRequest(r *http.Request) (*LanguageRequest, error) { lang := r.URL.Query().Get("lang") if lang == "" { lang = "en" } // Validate language if lang != "en" && lang != "es" { return nil, fmt.Errorf("unsupported language: %s (use 'en' or 'es')", lang) } return &LanguageRequest{Lang: lang}, nil } // PDFExportRequest represents all parameters for PDF export type PDFExportRequest struct { Lang string `validate:"required,oneof=en es"` // Language: "en" or "es" Length string `validate:"required,oneof=short long"` // Length: "short" or "long" Icons string `validate:"required,oneof=show hide"` // Icons: "show" or "hide" Version string `validate:"required,oneof=with_skills clean"` // Version: "with_skills" or "clean" } // ParsePDFExportRequest parses and validates PDF export parameters func ParsePDFExportRequest(r *http.Request) (*PDFExportRequest, error) { req := &PDFExportRequest{ Lang: r.URL.Query().Get("lang"), Length: r.URL.Query().Get("length"), Icons: r.URL.Query().Get("icons"), Version: r.URL.Query().Get("version"), } // Set defaults if req.Lang == "" { req.Lang = "en" } if req.Length == "" { req.Length = "short" } if req.Icons == "" { req.Icons = "show" } if req.Version == "" { req.Version = "with_skills" } // Validate language if req.Lang != "en" && req.Lang != "es" { return nil, fmt.Errorf("unsupported language: %s (use 'en' or 'es')", req.Lang) } // Validate length if req.Length != "short" && req.Length != "long" { return nil, fmt.Errorf("unsupported length: %s (use 'short' or 'long')", req.Length) } // Validate icons if req.Icons != "show" && req.Icons != "hide" { return nil, fmt.Errorf("unsupported icons option: %s (use 'show' or 'hide')", req.Icons) } // Validate version if req.Version != "with_skills" && req.Version != "clean" { return nil, fmt.Errorf("unsupported version: %s (use 'with_skills' or 'clean')", req.Version) } return req, nil } // PreferenceToggleRequest represents a toggle request with language context type PreferenceToggleRequest struct { Lang string // Current language from query or cookie } // ParsePreferenceToggleRequest parses toggle request parameters func ParsePreferenceToggleRequest(r *http.Request, defaultLang string) *PreferenceToggleRequest { lang := r.URL.Query().Get("lang") if lang == "" { lang = defaultLang } return &PreferenceToggleRequest{Lang: lang} } // ============================================================================== // RESPONSE TYPES // Structured response types for consistent API responses // ============================================================================== // APIResponse is a standardized response wrapper for JSON responses type APIResponse struct { Success bool `json:"success"` Data interface{} `json:"data,omitempty"` Error *ErrorInfo `json:"error,omitempty"` Meta *MetaInfo `json:"meta,omitempty"` } // ErrorInfo provides structured error information type ErrorInfo struct { Code string `json:"code"` // Error code (e.g., "INVALID_LANGUAGE") Message string `json:"message"` // Human-readable error message Field string `json:"field,omitempty"` // Field that caused the error Details string `json:"details,omitempty"` // Additional error details } // MetaInfo provides metadata about the response type MetaInfo struct { Timestamp int64 `json:"timestamp,omitempty"` // Unix timestamp Version string `json:"version,omitempty"` // API version RequestID string `json:"request_id,omitempty"` // Request tracking ID } // SuccessResponse creates a success response func SuccessResponse(data interface{}) *APIResponse { return &APIResponse{ Success: true, Data: data, } } // NewErrorResponse creates an error response func NewErrorResponse(code, message string) *APIResponse { return &APIResponse{ Success: false, Error: &ErrorInfo{ Code: code, Message: message, }, } } // ErrorResponseWithField creates an error response with field information func ErrorResponseWithField(code, message, field string) *APIResponse { return &APIResponse{ Success: false, Error: &ErrorInfo{ Code: code, Message: message, Field: field, }, } } // HealthCheckResponse represents health check endpoint response type HealthCheckResponse struct { Status string `json:"status"` // "healthy" or "unhealthy" Version string `json:"version"` // Application version Uptime int64 `json:"uptime,omitempty"` // Uptime in seconds Checks map[string]bool `json:"checks,omitempty"` // Component health checks }