sp4-v2-1770499323/services/chat-svc/internal/api/routes.go
rdev-worker 34f37a44b8
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
build: /implement-feature mesh-interop --requirements 'Chat Service must cal...
2026-02-07 21:49:45 +00:00

88 lines
2.9 KiB
Go

// Package api provides HTTP routing and handlers for the chat-svc service.
package api
import (
"context"
"git.threesix.ai/jordan/sp4-v2-1770499323/pkg/app"
"git.threesix.ai/jordan/sp4-v2-1770499323/pkg/auth"
"git.threesix.ai/jordan/sp4-v2-1770499323/services/chat-svc/internal/api/handlers"
"git.threesix.ai/jordan/sp4-v2-1770499323/services/chat-svc/internal/config"
"git.threesix.ai/jordan/sp4-v2-1770499323/services/chat-svc/internal/port"
"git.threesix.ai/jordan/sp4-v2-1770499323/services/chat-svc/internal/service"
)
// RegisterRoutes registers all HTTP routes for the service.
// Routes are mounted under /api/chat-svc to match the ingress path routing.
func RegisterRoutes(application *app.App, exampleService *service.ExampleService, authValidator port.AuthValidator, taskProducer port.TaskProducer) {
logger := application.Logger()
cfg := config.Load()
// Initialize handlers with injected services
healthHandler := handlers.NewHealth(logger)
exampleHandler := handlers.NewExample(exampleService, logger)
// Build and mount OpenAPI spec
spec := NewServiceSpec()
application.EnableDocs(spec)
// Register API routes under /api/{service-name} to match ingress path routing.
// The ingress routes /api/chat-svc/* to this service.
application.Route("/api/chat-svc", func(r app.Router) {
r.Get("/health", healthHandler.Check)
// Public routes (no auth required)
r.Get("/examples", app.Wrap(exampleHandler.List))
r.Get("/examples/{id}", app.Wrap(exampleHandler.Get))
// Protected routes (auth required when enabled)
r.Group(func(r app.Router) {
if cfg.AuthEnabled {
// Use auth-svc for token validation when available,
// otherwise fall back to local JWT validation.
var validator auth.Validator
if authValidator != nil {
validator = &authSvcValidator{client: authValidator}
} else {
validator = auth.NewJWTValidator(auth.JWTConfig{
Secret: []byte(cfg.JWTSecret),
Issuer: "sp4-v2-1770499323",
})
}
r.Use(auth.Middleware(auth.MiddlewareConfig{
Validator: validator,
}))
}
r.Post("/examples", app.Wrap(exampleHandler.Create))
r.Put("/examples/{id}", app.Wrap(exampleHandler.Update))
r.Delete("/examples/{id}", app.Wrap(exampleHandler.Delete))
// Task enqueue endpoint (requires auth, requires queue)
if taskProducer != nil {
taskHandler := handlers.NewTask(taskProducer, logger)
r.Post("/tasks", app.Wrap(taskHandler.Enqueue))
}
})
})
}
// authSvcValidator adapts port.AuthValidator to auth.Validator,
// allowing the auth-svc HTTP client to be used with auth.Middleware.
type authSvcValidator struct {
client port.AuthValidator
}
func (v *authSvcValidator) Validate(ctx context.Context, token string) (*auth.User, error) {
user, err := v.client.ValidateToken(ctx, token)
if err != nil {
return nil, err
}
return &auth.User{
ID: user.UserID,
Email: user.Email,
Roles: user.Roles,
Scopes: user.Scopes,
}, nil
}