package main import ( "flag" "fmt" "log" "net/http" "os" "os/signal" "syscall" "github.com/gorilla/mux" "github.com/insertr/server/internal/api" "github.com/insertr/server/internal/db" ) func main() { // Command line flags var ( port = flag.Int("port", 8080, "Server port") dbPath = flag.String("db", "./insertr.db", "SQLite database path") ) flag.Parse() // Initialize database database, err := db.NewSQLiteDB(*dbPath) if err != nil { log.Fatalf("Failed to initialize database: %v", err) } defer database.Close() // Initialize handlers contentHandler := api.NewContentHandler(database) // Setup router router := mux.NewRouter() // Add middleware router.Use(api.CORSMiddleware) router.Use(api.LoggingMiddleware) router.Use(api.ContentTypeMiddleware) // Health check endpoint router.HandleFunc("/health", api.HealthMiddleware()) // API routes apiRouter := router.PathPrefix("/api/content").Subrouter() // Content endpoints matching the expected API contract apiRouter.HandleFunc("/bulk", contentHandler.GetBulkContent).Methods("GET") apiRouter.HandleFunc("/{id}", contentHandler.GetContent).Methods("GET") apiRouter.HandleFunc("/{id}", contentHandler.UpdateContent).Methods("PUT") apiRouter.HandleFunc("", contentHandler.GetAllContent).Methods("GET") apiRouter.HandleFunc("", contentHandler.CreateContent).Methods("POST") // Handle CORS preflight requests explicitly apiRouter.HandleFunc("/{id}", api.CORSPreflightHandler).Methods("OPTIONS") apiRouter.HandleFunc("", api.CORSPreflightHandler).Methods("OPTIONS") apiRouter.HandleFunc("/bulk", api.CORSPreflightHandler).Methods("OPTIONS") // Start server addr := fmt.Sprintf(":%d", *port) fmt.Printf("šŸš€ Insertr Content Server starting...\n") fmt.Printf("šŸ“ Database: %s\n", *dbPath) fmt.Printf("🌐 Server running at: http://localhost%s\n", addr) fmt.Printf("šŸ’š Health check: http://localhost%s/health\n", addr) fmt.Printf("šŸ“Š API endpoints:\n") fmt.Printf(" GET /api/content?site_id={site}\n") fmt.Printf(" GET /api/content/{id}?site_id={site}\n") fmt.Printf(" GET /api/content/bulk?site_id={site}&ids[]={id1}&ids[]={id2}\n") fmt.Printf(" POST /api/content\n") fmt.Printf(" PUT /api/content/{id}\n") fmt.Printf("\nšŸ”„ Press Ctrl+C to shutdown gracefully\n\n") // Setup graceful shutdown server := &http.Server{ Addr: addr, Handler: router, } // Start server in a goroutine go func() { if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("Server failed to start: %v", err) } }() // Wait for interrupt signal quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit fmt.Println("\nšŸ›‘ Shutting down server...") if err := server.Close(); err != nil { log.Fatalf("Server forced to shutdown: %v", err) } fmt.Println("āœ… Server shutdown complete") }