Files
dance-lessons-coach/pkg/greet/api_v2.go
Gabriel Radureau c1e628f339 📝 docs: update comprehensive documentation and project infrastructure
Documentation Updates:
- Enhanced AGENTS.md with user authentication details
- Updated README.md with authentication API documentation
- Added CONTRIBUTING.md guidelines for BDD testing
- Version management guide improvements
- Local CI/CD testing documentation

Project Infrastructure:
- Updated .gitignore for new file patterns
- Enhanced git hooks documentation
- YAML linting configuration
- Script improvements and organization
- Configuration management updates

API Enhancements:
- Greet service integration with authentication
- Server middleware for JWT validation
- Telemetry improvements
- Version management utilities

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-04-09 00:26:15 +02:00

125 lines
3.4 KiB
Go

package greet
import (
"context"
"encoding/json"
"errors"
"io"
"net/http"
"strconv"
"dance-lessons-coach/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 API/v2/Greeting
// @Accept json
// @Produce json
// @Param request body GreetRequest true "Greeting request"
// @Success 200 {object} GreetResponseV2 "Successful response"
// @Failure 400 {object} ValidationError "Validation error"
// @Security BearerAuth
// @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})
}