| package main |
|
|
| import ( |
| "context" |
| "fmt" |
| "io" |
| "log" |
| "net/http" |
| "os" |
| "os/signal" |
| "strings" |
| "syscall" |
| "time" |
|
|
| "github.com/gin-contrib/cors" |
| "github.com/gin-gonic/gin" |
| "github.com/joho/godotenv" |
| ) |
|
|
| func main() { |
| _ = godotenv.Load() |
|
|
| cfg := LoadConfig() |
|
|
| |
| |
| if strings.ToUpper(cfg.LogLevel) == "NO" { |
| |
| |
| log.SetOutput(io.Discard) |
| log.Println("Logging is disabled.") |
| } |
| |
|
|
| if cfg.GinMode == "release" { |
| gin.SetMode(gin.ReleaseMode) |
| } else { |
| gin.SetMode(gin.DebugMode) |
| } |
| log.Printf("Starting Go Proxy Server in %s mode...", gin.Mode()) |
|
|
| router := gin.New() |
|
|
| |
| |
| if strings.ToUpper(cfg.LogLevel) != "NO" { |
| router.Use(gin.Logger()) |
| } |
| |
|
|
| router.Use(gin.Recovery()) |
| router.Use(cors.New(cors.Config{ |
| AllowOrigins: []string{"*"}, |
| AllowMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"}, |
| AllowHeaders: []string{"Origin", "Content-Length", "Content-Type", "Authorization", "X-API-Key"}, |
| ExposeHeaders: []string{"Content-Length"}, |
| AllowCredentials: true, |
| MaxAge: 12 * time.Hour, |
| })) |
|
|
| router.GET("/health", HealthCheckHandler) |
|
|
| v1 := router.Group("/v1") |
| { |
| if len(cfg.ValidAPIKeys) > 0 { |
| log.Printf("API Key authentication enabled (%d keys configured).", len(cfg.ValidAPIKeys)) |
| v1.Use(APIKeyAuthMiddleware(cfg.ValidAPIKeys)) |
| } else { |
| log.Println("WARN: No PROXY_API_KEYS configured. Proxy is open (no authentication).") |
| } |
| v1.POST("/messages", MessagesHandler) |
| } |
|
|
| server := &http.Server{ |
| Addr: fmt.Sprintf(":%s", cfg.Port), |
| Handler: router, |
| ReadTimeout: 10 * time.Second, |
| WriteTimeout: cfg.ReadTimeout + 30*time.Second, |
| IdleTimeout: 120 * time.Second, |
| } |
|
|
| go func() { |
| log.Printf("Server listening on port %s", cfg.Port) |
| if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { |
| log.Fatalf("listen: %s\n", err) |
| } |
| }() |
|
|
| quit := make(chan os.Signal, 1) |
| signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) |
| <-quit |
| log.Println("Shutting down server...") |
|
|
| ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| defer cancel() |
| if err := server.Shutdown(ctx); err != nil { |
| log.Fatal("Server forced to shutdown:", err) |
| } |
|
|
| log.Println("Server exiting") |
| } |
|
|