2025-12-03 19:29:37 +00:00
|
|
|
//go:build ignore
|
|
|
|
|
// +build ignore
|
|
|
|
|
|
|
|
|
|
// TODO: Réactiver api_manager.go après stabilisation du noyau et alignement des services (graphql, grpc, websocket, features)
|
|
|
|
|
|
|
|
|
|
package api
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/http"
|
|
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
|
|
|
|
|
"veza-backend-api/internal/api/graphql"
|
|
|
|
|
"veza-backend-api/internal/api/grpc"
|
|
|
|
|
"veza-backend-api/internal/api/websocket"
|
|
|
|
|
"veza-backend-api/internal/config"
|
|
|
|
|
"veza-backend-api/internal/database"
|
|
|
|
|
"veza-backend-api/internal/features"
|
|
|
|
|
"veza-backend-api/internal/middleware"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// APIManager manages all API protocols (REST, GraphQL, gRPC, WebSocket)
|
|
|
|
|
type APIManager struct {
|
|
|
|
|
config *config.Config
|
|
|
|
|
db *database.DB
|
|
|
|
|
|
|
|
|
|
// API Servers
|
|
|
|
|
restRouter *gin.Engine
|
|
|
|
|
graphqlServer *graphql.GraphQLServer
|
|
|
|
|
grpcServer *grpc.GRPCServer
|
|
|
|
|
websocketManager *websocket.WebSocketManager
|
|
|
|
|
|
|
|
|
|
// Feature integration
|
|
|
|
|
featureManager *features.FeatureManager
|
|
|
|
|
|
|
|
|
|
// HTTP Server
|
|
|
|
|
httpServer *http.Server
|
|
|
|
|
|
|
|
|
|
isRunning bool
|
|
|
|
|
mu sync.RWMutex
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// APIConfig contains configuration for all API protocols
|
|
|
|
|
type APIConfig struct {
|
|
|
|
|
REST RESTConfig `yaml:"rest"`
|
|
|
|
|
GraphQL graphql.GraphQLConfig `yaml:"graphql"`
|
|
|
|
|
GRPC grpc.GRPCConfig `yaml:"grpc"`
|
|
|
|
|
WebSocket websocket.WebSocketConfig `yaml:"websocket"`
|
|
|
|
|
Global GlobalAPIConfig `yaml:"global"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RESTConfig contains REST API configuration
|
|
|
|
|
type RESTConfig struct {
|
|
|
|
|
Enabled bool `yaml:"enabled"`
|
|
|
|
|
Host string `yaml:"host"`
|
|
|
|
|
Port int `yaml:"port"`
|
|
|
|
|
Mode string `yaml:"mode"` // debug, release, test
|
|
|
|
|
TrustedProxies []string `yaml:"trusted_proxies"`
|
|
|
|
|
MaxMultipartMemory int64 `yaml:"max_multipart_memory"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GlobalAPIConfig contains global API settings
|
|
|
|
|
type GlobalAPIConfig struct {
|
|
|
|
|
Timeout time.Duration `yaml:"timeout"`
|
|
|
|
|
ReadTimeout time.Duration `yaml:"read_timeout"`
|
|
|
|
|
WriteTimeout time.Duration `yaml:"write_timeout"`
|
|
|
|
|
IdleTimeout time.Duration `yaml:"idle_timeout"`
|
|
|
|
|
ShutdownTimeout time.Duration `yaml:"shutdown_timeout"`
|
|
|
|
|
CORS CORSConfig `yaml:"cors"`
|
|
|
|
|
RateLimit RateLimitConfig `yaml:"rate_limit"`
|
|
|
|
|
Security SecurityConfig `yaml:"security"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CORSConfig contains CORS configuration
|
|
|
|
|
type CORSConfig struct {
|
|
|
|
|
Enabled bool `yaml:"enabled"`
|
|
|
|
|
AllowOrigins []string `yaml:"allow_origins"`
|
|
|
|
|
AllowMethods []string `yaml:"allow_methods"`
|
|
|
|
|
AllowHeaders []string `yaml:"allow_headers"`
|
|
|
|
|
ExposeHeaders []string `yaml:"expose_headers"`
|
|
|
|
|
AllowCredentials bool `yaml:"allow_credentials"`
|
|
|
|
|
MaxAge int `yaml:"max_age"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RateLimitConfig contains rate limiting configuration
|
|
|
|
|
type RateLimitConfig struct {
|
|
|
|
|
Enabled bool `yaml:"enabled"`
|
|
|
|
|
RPS int `yaml:"rps"`
|
|
|
|
|
Burst int `yaml:"burst"`
|
|
|
|
|
Window time.Duration `yaml:"window"`
|
|
|
|
|
KeyFunc string `yaml:"key_func"` // ip, user, api_key
|
|
|
|
|
SkipPaths []string `yaml:"skip_paths"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SecurityConfig contains security configuration
|
|
|
|
|
type SecurityConfig struct {
|
|
|
|
|
Enabled bool `yaml:"enabled"`
|
|
|
|
|
JWTSecret string `yaml:"jwt_secret"`
|
|
|
|
|
APIKeyHeader string `yaml:"api_key_header"`
|
|
|
|
|
AllowedUserAgents []string `yaml:"allowed_user_agents"`
|
|
|
|
|
CSRFProtection bool `yaml:"csrf_protection"`
|
|
|
|
|
HTTPSOnly bool `yaml:"https_only"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewAPIManager creates a new API manager instance
|
|
|
|
|
func NewAPIManager(config *config.Config, db *database.DB, featureManager *features.FeatureManager) *APIManager {
|
|
|
|
|
return &APIManager{
|
|
|
|
|
config: config,
|
|
|
|
|
db: db,
|
|
|
|
|
featureManager: featureManager,
|
|
|
|
|
isRunning: false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize sets up all API protocols
|
|
|
|
|
func (am *APIManager) Initialize(apiConfig APIConfig) error {
|
|
|
|
|
am.mu.Lock()
|
|
|
|
|
defer am.mu.Unlock()
|
|
|
|
|
|
|
|
|
|
// Initialize REST API (Gin)
|
|
|
|
|
if err := am.initializeREST(apiConfig.REST, apiConfig.Global); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to initialize REST API: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize GraphQL server
|
|
|
|
|
if apiConfig.GraphQL.Enabled {
|
|
|
|
|
if err := am.initializeGraphQL(apiConfig.GraphQL); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to initialize GraphQL: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize gRPC server
|
|
|
|
|
if apiConfig.GRPC.Enabled {
|
|
|
|
|
if err := am.initializeGRPC(apiConfig.GRPC); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to initialize gRPC: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize WebSocket manager
|
|
|
|
|
if apiConfig.WebSocket.Enabled {
|
|
|
|
|
if err := am.initializeWebSocket(apiConfig.WebSocket); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to initialize WebSocket: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Setup HTTP server
|
|
|
|
|
am.setupHTTPServer(apiConfig)
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initializeREST sets up the REST API with Gin
|
|
|
|
|
func (am *APIManager) initializeREST(restConfig RESTConfig, globalConfig GlobalAPIConfig) error {
|
|
|
|
|
if !restConfig.Enabled {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set Gin mode
|
|
|
|
|
gin.SetMode(restConfig.Mode)
|
|
|
|
|
|
|
|
|
|
// Create Gin engine
|
|
|
|
|
am.restRouter = gin.New()
|
|
|
|
|
|
|
|
|
|
// Setup global middleware
|
|
|
|
|
am.setupGlobalMiddleware(globalConfig)
|
|
|
|
|
|
|
|
|
|
// Setup existing REST routes (from router.go)
|
|
|
|
|
am.setupExistingRESTRoutes()
|
|
|
|
|
|
|
|
|
|
// Setup feature-specific routes
|
|
|
|
|
am.setupFeatureRoutes()
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initializeGraphQL sets up the GraphQL server
|
|
|
|
|
func (am *APIManager) initializeGraphQL(graphqlConfig graphql.GraphQLConfig) error {
|
|
|
|
|
am.graphqlServer = graphql.NewGraphQLServer(am.config, am.db, nil) // logger would be added
|
|
|
|
|
am.graphqlServer.Configure(graphqlConfig)
|
|
|
|
|
am.graphqlServer.SetupRoutes(am.restRouter, graphqlConfig)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initializeGRPC sets up the gRPC server
|
|
|
|
|
func (am *APIManager) initializeGRPC(grpcConfig grpc.GRPCConfig) error {
|
|
|
|
|
am.grpcServer = grpc.NewGRPCServer(am.config, am.db)
|
|
|
|
|
return am.grpcServer.Initialize(grpcConfig)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initializeWebSocket sets up the WebSocket manager
|
|
|
|
|
func (am *APIManager) initializeWebSocket(wsConfig websocket.WebSocketConfig) error {
|
|
|
|
|
am.websocketManager = websocket.NewWebSocketManager(am.config, am.db)
|
|
|
|
|
if err := am.websocketManager.Initialize(wsConfig); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
am.websocketManager.SetupRoutes(am.restRouter, wsConfig)
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupGlobalMiddleware configures global middleware for REST API
|
|
|
|
|
func (am *APIManager) setupGlobalMiddleware(globalConfig GlobalAPIConfig) {
|
|
|
|
|
// Recovery middleware
|
|
|
|
|
am.restRouter.Use(gin.Recovery())
|
|
|
|
|
|
2025-12-27 00:50:39 +00:00
|
|
|
// FIX #7: Logger middleware dupliqué supprimé
|
|
|
|
|
// Le middleware.Logger() non structuré a été supprimé
|
|
|
|
|
// Utiliser RequestLogger() à la place si ce fichier est réactivé
|
|
|
|
|
// Note: Ce fichier est actuellement ignoré (//go:build ignore)
|
|
|
|
|
// am.restRouter.Use(middleware.RequestLogger(logger))
|
2025-12-03 19:29:37 +00:00
|
|
|
|
|
|
|
|
// CORS middleware
|
|
|
|
|
if globalConfig.CORS.Enabled {
|
|
|
|
|
am.restRouter.Use(middleware.CORS())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rate limiting middleware
|
|
|
|
|
if globalConfig.RateLimit.Enabled {
|
|
|
|
|
am.restRouter.Use(middleware.RateLimiter(globalConfig.RateLimit.RPS, globalConfig.RateLimit.Window))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Security middleware
|
|
|
|
|
if globalConfig.Security.Enabled {
|
|
|
|
|
am.restRouter.Use(middleware.Security())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Request ID middleware
|
|
|
|
|
am.restRouter.Use(middleware.RequestID())
|
|
|
|
|
|
|
|
|
|
// Timeout middleware
|
|
|
|
|
am.restRouter.Use(middleware.Timeout(globalConfig.Timeout))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupExistingRESTRoutes sets up the existing REST routes
|
|
|
|
|
func (am *APIManager) setupExistingRESTRoutes() {
|
|
|
|
|
// Use the existing APIRouter setup
|
|
|
|
|
SetupRoutes(am.restRouter, am.db, am.config)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupFeatureRoutes sets up feature-specific API routes
|
|
|
|
|
func (am *APIManager) setupFeatureRoutes() {
|
|
|
|
|
if am.featureManager == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// API v2 group for new feature-based endpoints
|
|
|
|
|
v2 := am.restRouter.Group("/api/v2")
|
|
|
|
|
{
|
|
|
|
|
// User domain features
|
|
|
|
|
am.setupUserDomainRoutes(v2)
|
|
|
|
|
|
|
|
|
|
// Communication domain features
|
|
|
|
|
am.setupCommunicationDomainRoutes(v2)
|
|
|
|
|
|
|
|
|
|
// Media domain features
|
|
|
|
|
am.setupMediaDomainRoutes(v2)
|
|
|
|
|
|
|
|
|
|
// AI domain features
|
|
|
|
|
am.setupAIDomainRoutes(v2)
|
|
|
|
|
|
|
|
|
|
// Analytics domain features
|
|
|
|
|
am.setupAnalyticsDomainRoutes(v2)
|
|
|
|
|
|
|
|
|
|
// Integration domain features
|
|
|
|
|
am.setupIntegrationDomainRoutes(v2)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Feature management endpoints
|
|
|
|
|
admin := am.restRouter.Group("/api/admin")
|
|
|
|
|
{
|
|
|
|
|
admin.GET("/features", am.handleGetFeatures)
|
|
|
|
|
admin.GET("/features/:id", am.handleGetFeature)
|
|
|
|
|
admin.POST("/features/:id/start", am.handleStartFeature)
|
|
|
|
|
admin.POST("/features/:id/stop", am.handleStopFeature)
|
|
|
|
|
admin.GET("/features/health", am.handleFeaturesHealth)
|
|
|
|
|
admin.GET("/features/metrics", am.handleFeaturesMetrics)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupUserDomainRoutes sets up user domain feature routes
|
|
|
|
|
func (am *APIManager) setupUserDomainRoutes(router *gin.RouterGroup) {
|
|
|
|
|
userGroup := router.Group("/user")
|
|
|
|
|
{
|
|
|
|
|
// User Profiles Feature endpoints
|
|
|
|
|
userGroup.GET("/profiles/:id", am.handleGetUserProfile)
|
|
|
|
|
userGroup.PUT("/profiles/:id", am.handleUpdateUserProfile)
|
|
|
|
|
|
|
|
|
|
// Social Graph Feature endpoints
|
|
|
|
|
userGroup.POST("/follow/:id", am.handleFollowUser)
|
|
|
|
|
userGroup.DELETE("/follow/:id", am.handleUnfollowUser)
|
|
|
|
|
userGroup.GET("/followers/:id", am.handleGetFollowers)
|
|
|
|
|
userGroup.GET("/following/:id", am.handleGetFollowing)
|
|
|
|
|
|
2026-02-16 10:03:27 +00:00
|
|
|
// Achievements endpoints
|
2025-12-03 19:29:37 +00:00
|
|
|
userGroup.GET("/achievements/:id", am.handleGetAchievements)
|
|
|
|
|
userGroup.GET("/leaderboard", am.handleGetLeaderboard)
|
|
|
|
|
userGroup.POST("/achievements/:id/claim", am.handleClaimAchievement)
|
|
|
|
|
|
|
|
|
|
// User Verification Feature endpoints
|
|
|
|
|
userGroup.POST("/verify", am.handleStartVerification)
|
|
|
|
|
userGroup.GET("/verify/status", am.handleGetVerificationStatus)
|
|
|
|
|
userGroup.GET("/trust-score/:id", am.handleGetTrustScore)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupCommunicationDomainRoutes sets up communication domain feature routes
|
|
|
|
|
func (am *APIManager) setupCommunicationDomainRoutes(router *gin.RouterGroup) {
|
|
|
|
|
commGroup := router.Group("/communication")
|
|
|
|
|
{
|
|
|
|
|
// Chat Rooms Feature endpoints
|
|
|
|
|
commGroup.GET("/rooms", am.handleGetRooms)
|
|
|
|
|
commGroup.POST("/rooms", am.handleCreateRoom)
|
|
|
|
|
commGroup.GET("/rooms/:id", am.handleGetRoom)
|
|
|
|
|
commGroup.POST("/rooms/:id/join", am.handleJoinRoom)
|
|
|
|
|
commGroup.POST("/rooms/:id/leave", am.handleLeaveRoom)
|
|
|
|
|
|
|
|
|
|
// Voice Chat Feature endpoints
|
|
|
|
|
commGroup.POST("/voice/start", am.handleStartVoiceChat)
|
|
|
|
|
commGroup.POST("/voice/stop", am.handleStopVoiceChat)
|
|
|
|
|
commGroup.GET("/voice/status", am.handleGetVoiceStatus)
|
|
|
|
|
|
|
|
|
|
// Video Streaming Feature endpoints
|
|
|
|
|
commGroup.POST("/video/start", am.handleStartVideoStream)
|
|
|
|
|
commGroup.POST("/video/stop", am.handleStopVideoStream)
|
|
|
|
|
commGroup.GET("/video/streams", am.handleGetVideoStreams)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupMediaDomainRoutes sets up media domain feature routes
|
|
|
|
|
func (am *APIManager) setupMediaDomainRoutes(router *gin.RouterGroup) {
|
|
|
|
|
mediaGroup := router.Group("/media")
|
|
|
|
|
{
|
|
|
|
|
// Audio Streaming Feature endpoints
|
|
|
|
|
mediaGroup.POST("/audio/upload", am.handleUploadAudio)
|
|
|
|
|
mediaGroup.GET("/audio/:id/stream", am.handleStreamAudio)
|
|
|
|
|
mediaGroup.GET("/audio/:id/metadata", am.handleGetAudioMetadata)
|
|
|
|
|
|
|
|
|
|
// Smart Playlists Feature endpoints
|
|
|
|
|
mediaGroup.GET("/playlists/smart", am.handleGetSmartPlaylists)
|
|
|
|
|
mediaGroup.POST("/playlists/smart", am.handleCreateSmartPlaylist)
|
|
|
|
|
mediaGroup.GET("/playlists/smart/:id", am.handleGetSmartPlaylist)
|
|
|
|
|
|
|
|
|
|
// Content Discovery Feature endpoints
|
|
|
|
|
mediaGroup.GET("/discover", am.handleDiscoverContent)
|
|
|
|
|
mediaGroup.GET("/trending", am.handleGetTrending)
|
|
|
|
|
mediaGroup.GET("/similar/:id", am.handleGetSimilarContent)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupAIDomainRoutes sets up AI domain feature routes
|
|
|
|
|
func (am *APIManager) setupAIDomainRoutes(router *gin.RouterGroup) {
|
|
|
|
|
aiGroup := router.Group("/ai")
|
|
|
|
|
{
|
|
|
|
|
// Smart Recommendations Feature endpoints
|
|
|
|
|
aiGroup.GET("/recommendations", am.handleGetRecommendations)
|
|
|
|
|
aiGroup.POST("/recommendations/feedback", am.handleRecommendationFeedback)
|
|
|
|
|
|
|
|
|
|
// Content Moderation Feature endpoints
|
|
|
|
|
aiGroup.POST("/moderate", am.handleModerateContent)
|
|
|
|
|
aiGroup.GET("/moderation/history", am.handleGetModerationHistory)
|
|
|
|
|
|
|
|
|
|
// Sentiment Analysis Feature endpoints
|
|
|
|
|
aiGroup.POST("/sentiment", am.handleAnalyzeSentiment)
|
|
|
|
|
aiGroup.GET("/sentiment/trends", am.handleGetSentimentTrends)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupAnalyticsDomainRoutes sets up analytics domain feature routes
|
|
|
|
|
func (am *APIManager) setupAnalyticsDomainRoutes(router *gin.RouterGroup) {
|
|
|
|
|
analyticsGroup := router.Group("/analytics")
|
|
|
|
|
{
|
|
|
|
|
// Realtime Dashboards Feature endpoints
|
|
|
|
|
analyticsGroup.GET("/dashboard", am.handleGetDashboard)
|
|
|
|
|
analyticsGroup.GET("/metrics/realtime", am.handleGetRealtimeMetrics)
|
|
|
|
|
|
|
|
|
|
// User Behavior Analytics Feature endpoints
|
|
|
|
|
analyticsGroup.GET("/behavior/:id", am.handleGetUserBehavior)
|
|
|
|
|
analyticsGroup.GET("/engagement", am.handleGetEngagementMetrics)
|
|
|
|
|
|
|
|
|
|
// Business Analytics Feature endpoints
|
|
|
|
|
analyticsGroup.GET("/business/revenue", am.handleGetRevenueAnalytics)
|
|
|
|
|
analyticsGroup.GET("/business/conversion", am.handleGetConversionMetrics)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupIntegrationDomainRoutes sets up integration domain feature routes
|
|
|
|
|
func (am *APIManager) setupIntegrationDomainRoutes(router *gin.RouterGroup) {
|
|
|
|
|
integrationGroup := router.Group("/integration")
|
|
|
|
|
{
|
|
|
|
|
// External API Gateway Feature endpoints
|
|
|
|
|
integrationGroup.POST("/external/request", am.handleExternalAPIRequest)
|
|
|
|
|
integrationGroup.GET("/external/status", am.handleGetExternalAPIStatus)
|
|
|
|
|
|
|
|
|
|
// Webhook System Feature endpoints
|
|
|
|
|
integrationGroup.POST("/webhooks", am.handleCreateWebhook)
|
|
|
|
|
integrationGroup.GET("/webhooks", am.handleGetWebhooks)
|
|
|
|
|
integrationGroup.DELETE("/webhooks/:id", am.handleDeleteWebhook)
|
|
|
|
|
|
|
|
|
|
// Payment Gateways Feature endpoints
|
|
|
|
|
integrationGroup.POST("/payments/process", am.handleProcessPayment)
|
|
|
|
|
integrationGroup.GET("/payments/methods", am.handleGetPaymentMethods)
|
|
|
|
|
integrationGroup.GET("/payments/history", am.handleGetPaymentHistory)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setupHTTPServer configures the HTTP server
|
|
|
|
|
func (am *APIManager) setupHTTPServer(apiConfig APIConfig) {
|
|
|
|
|
addr := fmt.Sprintf("%s:%d", apiConfig.REST.Host, apiConfig.REST.Port)
|
|
|
|
|
|
|
|
|
|
am.httpServer = &http.Server{
|
|
|
|
|
Addr: addr,
|
|
|
|
|
Handler: am.restRouter,
|
|
|
|
|
ReadTimeout: apiConfig.Global.ReadTimeout,
|
|
|
|
|
WriteTimeout: apiConfig.Global.WriteTimeout,
|
|
|
|
|
IdleTimeout: apiConfig.Global.IdleTimeout,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start starts all API servers
|
|
|
|
|
func (am *APIManager) Start(ctx context.Context) error {
|
|
|
|
|
am.mu.Lock()
|
|
|
|
|
defer am.mu.Unlock()
|
|
|
|
|
|
|
|
|
|
if am.isRunning {
|
|
|
|
|
return fmt.Errorf("API manager is already running")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start gRPC server if enabled
|
|
|
|
|
if am.grpcServer != nil {
|
|
|
|
|
if err := am.grpcServer.Start(ctx); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to start gRPC server: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start WebSocket manager if enabled
|
|
|
|
|
if am.websocketManager != nil {
|
|
|
|
|
if err := am.websocketManager.Start(ctx); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to start WebSocket manager: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start HTTP server (REST + GraphQL)
|
|
|
|
|
go func() {
|
|
|
|
|
if err := am.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
|
|
|
// Handle error
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
am.isRunning = true
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Stop stops all API servers
|
|
|
|
|
func (am *APIManager) Stop(ctx context.Context) error {
|
|
|
|
|
am.mu.Lock()
|
|
|
|
|
defer am.mu.Unlock()
|
|
|
|
|
|
|
|
|
|
if !am.isRunning {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Stop HTTP server
|
|
|
|
|
if am.httpServer != nil {
|
|
|
|
|
if err := am.httpServer.Shutdown(ctx); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to stop HTTP server: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Stop WebSocket manager
|
|
|
|
|
if am.websocketManager != nil {
|
|
|
|
|
if err := am.websocketManager.Stop(ctx); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to stop WebSocket manager: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Stop gRPC server
|
|
|
|
|
if am.grpcServer != nil {
|
|
|
|
|
if err := am.grpcServer.Stop(ctx); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to stop gRPC server: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Stop GraphQL server
|
|
|
|
|
if am.graphqlServer != nil {
|
|
|
|
|
if err := am.graphqlServer.Shutdown(ctx); err != nil {
|
|
|
|
|
return fmt.Errorf("failed to stop GraphQL server: %w", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
am.isRunning = false
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IsHealthy checks if all API servers are healthy
|
|
|
|
|
func (am *APIManager) IsHealthy() bool {
|
|
|
|
|
am.mu.RLock()
|
|
|
|
|
defer am.mu.RUnlock()
|
|
|
|
|
|
|
|
|
|
if !am.isRunning {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check each server's health
|
|
|
|
|
if am.grpcServer != nil && !am.grpcServer.IsHealthy() {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if am.websocketManager != nil && !am.websocketManager.IsHealthy() {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if am.graphqlServer != nil && !am.graphqlServer.IsHealthy() {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetAPIStatus returns comprehensive API status
|
|
|
|
|
func (am *APIManager) GetAPIStatus() map[string]interface{} {
|
|
|
|
|
am.mu.RLock()
|
|
|
|
|
defer am.mu.RUnlock()
|
|
|
|
|
|
|
|
|
|
status := map[string]interface{}{
|
|
|
|
|
"status": "healthy",
|
|
|
|
|
"running": am.isRunning,
|
|
|
|
|
"timestamp": time.Now(),
|
|
|
|
|
"apis": map[string]interface{}{},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
apis := status["apis"].(map[string]interface{})
|
|
|
|
|
|
|
|
|
|
// REST API status
|
|
|
|
|
apis["rest"] = map[string]interface{}{
|
|
|
|
|
"enabled": am.restRouter != nil,
|
|
|
|
|
"status": "healthy",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GraphQL status
|
|
|
|
|
if am.graphqlServer != nil {
|
|
|
|
|
apis["graphql"] = am.graphqlServer.GetMetrics()
|
|
|
|
|
} else {
|
|
|
|
|
apis["graphql"] = map[string]interface{}{"enabled": false}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// gRPC status
|
|
|
|
|
if am.grpcServer != nil {
|
|
|
|
|
apis["grpc"] = am.grpcServer.GetMetrics()
|
|
|
|
|
} else {
|
|
|
|
|
apis["grpc"] = map[string]interface{}{"enabled": false}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WebSocket status
|
|
|
|
|
if am.websocketManager != nil {
|
|
|
|
|
apis["websocket"] = am.websocketManager.GetMetrics()
|
|
|
|
|
} else {
|
|
|
|
|
apis["websocket"] = map[string]interface{}{"enabled": false}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return status
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Feature management handlers
|
|
|
|
|
func (am *APIManager) handleGetFeatures(c *gin.Context) {
|
|
|
|
|
if am.featureManager == nil {
|
|
|
|
|
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Feature manager not available"})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
summary := am.featureManager.GetFeatureSummary()
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"data": summary})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (am *APIManager) handleGetFeature(c *gin.Context) {
|
|
|
|
|
featureID := c.Param("id")
|
|
|
|
|
|
|
|
|
|
if am.featureManager == nil {
|
|
|
|
|
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Feature manager not available"})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
feature, err := am.featureManager.GetFeature(c.Request.Context(), featureID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"data": map[string]interface{}{
|
|
|
|
|
"id": feature.GetID(),
|
|
|
|
|
"name": feature.GetName(),
|
|
|
|
|
"version": feature.GetVersion(),
|
|
|
|
|
"type": feature.GetType(),
|
|
|
|
|
"domain": feature.GetDomain(),
|
|
|
|
|
"healthy": feature.IsHealthy(),
|
|
|
|
|
"status": feature.GetHealthStatus(),
|
|
|
|
|
"metrics": feature.GetMetrics(),
|
|
|
|
|
}})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (am *APIManager) handleStartFeature(c *gin.Context) {
|
|
|
|
|
// TODO: Implement feature start
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (am *APIManager) handleStopFeature(c *gin.Context) {
|
|
|
|
|
// TODO: Implement feature stop
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (am *APIManager) handleFeaturesHealth(c *gin.Context) {
|
|
|
|
|
if am.featureManager == nil {
|
|
|
|
|
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Feature manager not available"})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
healthStatus := am.featureManager.GetFeatureHealthStatus()
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"data": healthStatus})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (am *APIManager) handleFeaturesMetrics(c *gin.Context) {
|
|
|
|
|
if am.featureManager == nil {
|
|
|
|
|
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Feature manager not available"})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Implement comprehensive metrics collection
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"data": "metrics"})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Placeholder handlers for feature endpoints (to be implemented)
|
|
|
|
|
func (am *APIManager) handleGetUserProfile(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleUpdateUserProfile(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleFollowUser(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleUnfollowUser(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetFollowers(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetFollowing(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetAchievements(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetLeaderboard(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleClaimAchievement(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleStartVerification(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetVerificationStatus(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetTrustScore(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetRooms(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleCreateRoom(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetRoom(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleJoinRoom(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleLeaveRoom(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleStartVoiceChat(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleStopVoiceChat(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetVoiceStatus(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleStartVideoStream(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleStopVideoStream(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetVideoStreams(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleUploadAudio(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleStreamAudio(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetAudioMetadata(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetSmartPlaylists(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleCreateSmartPlaylist(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetSmartPlaylist(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleDiscoverContent(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetTrending(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetSimilarContent(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetRecommendations(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleRecommendationFeedback(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleModerateContent(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetModerationHistory(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleAnalyzeSentiment(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetSentimentTrends(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetDashboard(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetRealtimeMetrics(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetUserBehavior(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetEngagementMetrics(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetRevenueAnalytics(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetConversionMetrics(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleExternalAPIRequest(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetExternalAPIStatus(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleCreateWebhook(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetWebhooks(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleDeleteWebhook(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleProcessPayment(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetPaymentMethods(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|
|
|
|
|
func (am *APIManager) handleGetPaymentHistory(c *gin.Context) {
|
|
|
|
|
c.JSON(http.StatusNotImplemented, gin.H{"error": "Not implemented"})
|
|
|
|
|
}
|