Newer
Older
EnvoyControlPlane / internal / pkg / server / server.go
// internal/server/server.go
package server

import (
	"context"
	"fmt"
	"net/http"
	"time"

	internallog "envoy-control-plane/internal/log"
	"envoy-control-plane/internal/pkg/api"
)

// RunRESTServer starts the REST API server with graceful shutdown support.
func RunRESTServer(ctx context.Context, mux *http.ServeMux, restPort uint, webrootPath string, enableCertIssuance bool) {
	log := internallog.LogFromContext(ctx)

	corsHandler := api.CORS(mux)

	restAddr := fmt.Sprintf(":%d", restPort)
	log.Infof("starting REST API server on %s", restAddr)

	if enableCertIssuance {
		log.Infof("ACME challenge path configured: %s/ -> %s", api.ACME_CALLENGE_WEB_PATH, webrootPath)
	}

	srv := &http.Server{
		Addr:    restAddr,
		Handler: corsHandler,
	}

	// Shutdown goroutine
	go func() {
		<-ctx.Done()
		log.Infof("REST API server shutting down gracefully...")
		shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		if err := srv.Shutdown(shutdownCtx); err != nil {
			log.Errorf("REST API server forced to shutdown: %v", err)
		}
	}()

	// Start server (blocking)
	err := srv.ListenAndServe()
	if err != nil && err != http.ErrServerClosed {
		log.Errorf("REST server error: %v", err)
	}
}