All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 46s
Add a comprehensive guide for developers transitioning from Node/PHP and implement a new middleware to handle IP-based rate limiting with temporary banning functionality. Also refactors configuration loading to use a singleton pattern for better resource management.
74 lines
1.6 KiB
Go
74 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/chi/v5/middleware"
|
|
"github.com/go-chi/httprate"
|
|
"github.com/jmoiron/sqlx"
|
|
"github.com/joho/godotenv"
|
|
|
|
"emly-api-go/internal/config"
|
|
"emly-api-go/internal/database"
|
|
"emly-api-go/internal/database/schema"
|
|
"emly-api-go/internal/routes"
|
|
|
|
emlyMiddleware "emly-api-go/internal/middleware"
|
|
)
|
|
|
|
func main() {
|
|
// Load .env (ignored if not present in production)
|
|
_ = godotenv.Load()
|
|
|
|
cfg := config.Load()
|
|
|
|
db, err := database.Connect(cfg)
|
|
if err != nil {
|
|
log.Fatalf("database connection failed: %v", err)
|
|
}
|
|
defer func(db *sqlx.DB) {
|
|
err := db.Close()
|
|
if err != nil {
|
|
log.Fatalf("closing database failed: %v", err)
|
|
}
|
|
}(db)
|
|
|
|
// Run conditional schema migrations
|
|
if err := schema.Migrate(db, cfg.Database); err != nil {
|
|
log.Fatalf("schema migration failed: %v", err)
|
|
}
|
|
|
|
r := chi.NewRouter()
|
|
|
|
// Global middlewares
|
|
r.Use(middleware.RequestID)
|
|
r.Use(middleware.RealIP)
|
|
r.Use(middleware.Logger)
|
|
r.Use(middleware.Recoverer)
|
|
r.Use(middleware.Timeout(30 * time.Second))
|
|
|
|
// Global rate limit to 100 requests per minute
|
|
r.Use(httprate.LimitByIP(100, time.Minute))
|
|
|
|
rl := emlyMiddleware.NewRateLimiter(
|
|
5, // 5 req/sec per IP
|
|
10, // burst fino a 10
|
|
20, // ban dopo 20 violazioni
|
|
30*time.Minute, // ban di 15 minuti
|
|
)
|
|
|
|
r.Use(rl.Handler)
|
|
|
|
routes.RegisterAll(r, db)
|
|
|
|
addr := fmt.Sprintf(":%s", cfg.Port)
|
|
log.Printf("server listening on %s", addr)
|
|
if err := http.ListenAndServe(addr, r); err != nil {
|
|
log.Fatalf("server error: %v", err)
|
|
}
|
|
}
|