package greet import ( "context" "encoding/json" "errors" "io" "net/http" "strconv" "DanceLessonsCoach/pkg/validation" "github.com/go-chi/chi/v5" "github.com/rs/zerolog/log" ) type GreeterV2 interface { GreetV2(ctx context.Context, name string) string } type ApiV2Greet interface { RegisterRoutes(router chi.Router) } type apiV2GreetHandler struct { greeter GreeterV2 validator *validation.Validator } func NewApiV2GreetHandler(greeter GreeterV2, validator *validation.Validator) ApiV2Greet { return &apiV2GreetHandler{greeter: greeter, validator: validator} } func (h *apiV2GreetHandler) RegisterRoutes(router chi.Router) { log.Trace().Msg("Registering v2 greet routes") router.Post("/", h.handleGreetPost) log.Trace().Msg("v2 Greet routes registered") } type greetRequest struct { Name string `json:"name" validate:"max=100"` } type greetResponse struct { Message string `json:"message"` } // handleGreetPost godoc // @Summary Get greeting (v2) // @Description Returns a greeting message with validation (v2) // @Tags greet // @Accept json // @Produce json // @Param request body GreetRequest true "Greeting request" // @Success 200 {object} GreetResponseV2 "Successful response" // @Failure 400 {object} ValidationError "Validation error" // @Router /v2/greet [post] func (h *apiV2GreetHandler) handleGreetPost(w http.ResponseWriter, r *http.Request) { // Read request body body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, `{"error":"failed to read request body"}`, http.StatusBadRequest) return } // Parse JSON var req greetRequest if err := json.Unmarshal(body, &req); err != nil { http.Error(w, `{"error":"invalid JSON format"}`, http.StatusBadRequest) return } // Validate request if validator is available if h.validator != nil { log.Trace().Str("name", req.Name).Msg("Validating request") if err := h.validator.Validate(req); err != nil { log.Trace().Err(err).Msg("Validation failed") h.handleValidationError(w, err) return } log.Trace().Msg("Validation passed") } // Call service message := h.greeter.GreetV2(r.Context(), req.Name) // Write response h.writeJSONResponse(w, message) } func (h *apiV2GreetHandler) handleValidationError(w http.ResponseWriter, err error) { var validationErr *validation.ValidationError if errors.As(err, &validationErr) { // Create structured validation error response response := map[string]interface{}{ "error": "validation_failed", "message": "Invalid request data", "details": make([]map[string]string, 0, len(validationErr.Messages)), } // Parse validation messages into structured format for _, msg := range validationErr.Messages { // Simple parsing - in production, use proper parsing detail := map[string]string{ "message": msg, } response["details"] = append(response["details"].([]map[string]string), detail) } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(response) } else { // Fallback for other types of errors http.Error(w, `{"error":"validation_error","message":`+strconv.Quote(err.Error())+`}`, http.StatusBadRequest) } } func (h *apiV2GreetHandler) writeJSONResponse(w http.ResponseWriter, message string) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(greetResponse{Message: message}) }