@@ -12,7 +12,9 @@ import (
1212 "bullet-cloud-api/internal/products"
1313 "bullet-cloud-api/internal/users"
1414 "context"
15+ "fmt"
1516 "log"
17+ "net"
1618 "net/http"
1719 "os"
1820 "os/signal"
@@ -23,7 +25,7 @@ import (
2325 "github.com/gorilla/mux"
2426)
2527
26- const defaultPort = "4444"
28+ const defaultPortStart = 4445
2729const defaultJWTExpiry = 24 * time .Hour
2830
2931func main () {
@@ -60,20 +62,30 @@ func main() {
6062 r := setupRoutes (authHandler , userHandler , productHandler , categoryHandler , cartHandler , orderHandler , authMiddleware )
6163
6264 // --- Determine Port ---
63- port := os .Getenv ("PORT" ) // 1. Check Render's/Environment PORT variable
65+ port := os .Getenv ("PORT" )
6466 if port == "" {
65- port = defaultPort // 2. Use default if PORT is not set
66- }
67- // Basic validation (optional but recommended)
68- if _ , err := strconv .Atoi (port ); err != nil {
69- log .Fatalf ("Invalid port number: %s" , port )
67+ for p := defaultPortStart ; p < defaultPortStart + 100 ; p ++ {
68+ addr := fmt .Sprintf (":%d" , p )
69+ ln , err := net .Listen ("tcp" , addr )
70+ if err == nil {
71+ ln .Close ()
72+ port = strconv .Itoa (p )
73+ log .Printf ("PORT not set. Using first available port: %s" , port )
74+ break
75+ }
76+ }
77+ if port == "" {
78+ log .Fatal ("No available ports found from 4445 to 4545" )
79+ }
80+ } else {
81+ log .Printf ("Using PORT from environment: %s" , port )
7082 }
7183 listenAddr := ":" + port
7284 // --- End Determine Port ---
7385
7486 // Configure HTTP server
7587 srv := & http.Server {
76- Addr : listenAddr , // Use the determined address
88+ Addr : listenAddr ,
7789 Handler : r ,
7890 ReadTimeout : 5 * time .Second ,
7991 WriteTimeout : 10 * time .Second ,
@@ -84,19 +96,16 @@ func main() {
8496 done := make (chan os.Signal , 1 )
8597 signal .Notify (done , os .Interrupt , syscall .SIGINT , syscall .SIGTERM )
8698
87- // Start server in a goroutine
8899 go func () {
89100 log .Printf ("Server starting on port %s" , port )
90101 if err := srv .ListenAndServe (); err != nil && err != http .ErrServerClosed {
91102 log .Fatalf ("listen: %s\n " , err )
92103 }
93104 }()
94105
95- // Wait for shutdown signal
96106 <- done
97107 log .Println ("Server shutting down gracefully..." )
98108
99- // Create context for shutdown
100109 ctx , cancel := context .WithTimeout (context .Background (), 30 * time .Second )
101110 defer cancel ()
102111
@@ -108,9 +117,16 @@ func main() {
108117}
109118
110119// setupRoutes configures the API routes using mux router.
111- func setupRoutes (ah * handlers.AuthHandler , uh * handlers.UserHandler , ph * handlers.ProductHandler , ch * handlers.CategoryHandler , cartH * handlers.CartHandler , oh * handlers.OrderHandler , mw * auth.Middleware ) * mux.Router {
120+ func setupRoutes (
121+ ah * handlers.AuthHandler ,
122+ uh * handlers.UserHandler ,
123+ ph * handlers.ProductHandler ,
124+ ch * handlers.CategoryHandler ,
125+ cartH * handlers.CartHandler ,
126+ oh * handlers.OrderHandler ,
127+ mw * auth.Middleware ,
128+ ) * mux.Router {
112129 r := mux .NewRouter ()
113-
114130 apiV1 := r .PathPrefix ("/api" ).Subrouter ()
115131
116132 // Public routes
@@ -122,7 +138,7 @@ func setupRoutes(ah *handlers.AuthHandler, uh *handlers.UserHandler, ph *handler
122138 apiV1 .HandleFunc ("/categories" , ch .GetAllCategories ).Methods ("GET" )
123139 apiV1 .HandleFunc ("/categories/{id:[0-9a-fA-F-]+}" , ch .GetCategory ).Methods ("GET" )
124140
125- // Protected routes (grouped by resource)
141+ // Protected routes
126142 protectedUserRoutes := apiV1 .PathPrefix ("/users" ).Subrouter ()
127143 protectedUserRoutes .Use (mw .Authenticate )
128144 protectedUserRoutes .HandleFunc ("/me" , uh .GetMe ).Methods ("GET" )
0 commit comments