Files
wild-central-api/main.go
2025-10-12 16:52:36 +00:00

141 lines
3.7 KiB
Go

package main
import (
"fmt"
"log"
"net/http"
"os"
"strings"
"time"
"github.com/gorilla/mux"
"github.com/rs/cors"
v1 "github.com/wild-cloud/wild-central/daemon/internal/api/v1"
)
var startTime time.Time
// splitAndTrim splits a string by delimiter and trims whitespace from each part
func splitAndTrim(s string, sep string) []string {
parts := strings.Split(s, sep)
result := make([]string, 0, len(parts))
for _, part := range parts {
if trimmed := strings.TrimSpace(part); trimmed != "" {
result = append(result, trimmed)
}
}
return result
}
func main() {
// Record start time
startTime = time.Now()
// Get data directory from environment or use default
dataDir := os.Getenv("WILD_API_DATA_DIR")
if dataDir == "" {
dataDir = "/var/lib/wild-central"
}
// Get apps directory from environment or use default
// Note: Setup files (cluster-services, cluster-nodes, etc.) are now embedded in the binary
appsDir := os.Getenv("WILD_DIRECTORY")
if appsDir == "" {
// Default apps directory
appsDir = "/opt/wild-cloud/apps"
log.Printf("WILD_DIRECTORY not set, using default apps directory: %s", appsDir)
} else {
// If WILD_DIRECTORY is set, use it as-is for backward compatibility
// (it might point to the old directory structure with apps/ subdirectory)
log.Printf("Using WILD_DIRECTORY for apps: %s", appsDir)
}
// Create API handler with all dependencies
api, err := v1.NewAPI(dataDir, appsDir)
if err != nil {
log.Fatalf("Failed to initialize API: %v", err)
}
// Set up HTTP router
router := mux.NewRouter()
// Register Phase 1 API routes
api.RegisterRoutes(router)
// Health check endpoint
router.HandleFunc("/api/v1/health", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `{"status":"ok"}`)
}).Methods("GET")
// Status endpoint
router.HandleFunc("/api/v1/status", func(w http.ResponseWriter, r *http.Request) {
api.StatusHandler(w, r, startTime, dataDir, appsDir)
}).Methods("GET")
// Configure CORS
// Default to development origins
allowedOrigins := []string{
"http://localhost:5173", // Vite dev server
"http://localhost:5174", // Alternative port
"http://localhost:3000", // Common React dev port
"http://127.0.0.1:5173",
"http://127.0.0.1:5174",
"http://127.0.0.1:3000",
}
// Override with production origins if set
if corsOrigins := os.Getenv("WILD_CORS_ORIGINS"); corsOrigins != "" {
// Split comma-separated origins
allowedOrigins = []string{}
for _, origin := range splitAndTrim(corsOrigins, ",") {
allowedOrigins = append(allowedOrigins, origin)
}
log.Printf("CORS configured for production origins: %v", allowedOrigins)
} else {
log.Printf("CORS configured for development origins")
}
corsHandler := cors.New(cors.Options{
AllowedOrigins: allowedOrigins,
AllowedMethods: []string{
http.MethodGet,
http.MethodPost,
http.MethodPut,
http.MethodPatch,
http.MethodDelete,
http.MethodOptions,
},
AllowedHeaders: []string{
"Accept",
"Authorization",
"Content-Type",
"X-CSRF-Token",
},
ExposedHeaders: []string{
"Link",
},
AllowCredentials: true,
MaxAge: 300, // 5 minutes
})
// Wrap router with CORS middleware
handler := corsHandler.Handler(router)
// Default server settings
host := "0.0.0.0"
port := 5055
addr := fmt.Sprintf("%s:%d", host, port)
log.Printf("Starting wild-central daemon on %s", addr)
log.Printf("Data directory: %s", dataDir)
log.Printf("Apps directory: %s", appsDir)
log.Printf("CORS enabled for development origins")
if err := http.ListenAndServe(addr, handler); err != nil {
log.Fatal("Server failed to start:", err)
}
}