/
advanceddev
/
license-server
Обзор
Документация
Войти
/
advanceddev
/
license-server
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
2
CI/CD
Аналитика
Безопасность
master
cmd/server/main.go
135 строк
3 KB
advanceddev
feat: add custom params (JSONB) to licenses
09 авг 2026, 23:34
Не верифицирован
09 авг 2026, 23:34
64a191a
Код
Авторство
О чём код?
// Package main -- package main import ( "context" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "github.com/go-chi/chi/v5" chimw "github.com/go-chi/chi/v5/middleware" "github.com/jackc/pgx/v5/pgxpool" "gitverse.ru/advanceddev/license-server/internal/config" "gitverse.ru/advanceddev/license-server/internal/handler" mw "gitverse.ru/advanceddev/license-server/internal/middleware" "gitverse.ru/advanceddev/license-server/internal/repository" ) func main() { // === Logger === logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ Level: slog.LevelInfo, })) slog.SetDefault(logger) // === Config === cfg := config.Load() cfg.Validate() ctx := context.Background() // === PostgreSQL === pool, err := pgxpool.New(ctx, cfg.DatabaseURL) if err != nil { slog.Error("failed to connect to database", "error", err) os.Exit(1) } if err := pool.Ping(ctx); err != nil { slog.Error("failed to ping database", "error", err) os.Exit(1) } slog.Info("connected to PostgreSQL") // === Redis === redisClient, err := repository.NewRedisClient(ctx, cfg.RedisURL) if err != nil { slog.Error("failed to connect to redis", "error", err) os.Exit(1) } slog.Info("connected to Redis") // === Dependencies === licenseRepo := repository.NewLicenseRepository(pool) auditRepo := repository.NewAuditRepository(pool) licenseCache := repository.NewLicenseCache(redisClient, cfg.CacheTTL) validateLimiter := mw.NewRateLimiter( redisClient, cfg.RateLimitValidate, cfg.RateLimitWindow, "rl:validate", ) keyLimiter := mw.NewRateLimiter( redisClient, cfg.RateLimitPerKey, cfg.RateLimitPerKeyWindow, "rl:key", ) licenseHandler := handler.NewLicenseHandler(licenseRepo, licenseCache, auditRepo, validateLimiter, keyLimiter) adminHandler := handler.NewAdminHandler(licenseRepo, licenseCache, auditRepo, cfg.DefaultLicenseDuration) healthHandler := handler.NewHealthHandler(pool, redisClient) // === Router === r := chi.NewRouter() r.Use(chimw.Recoverer) r.Use(chimw.ClientIPFromRemoteAddr) r.Use(chimw.Timeout(10 * time.Second)) r.Use(mw.RequestID) r.Use(chimw.Logger) r.Use(mw.SlogRequestLogger) // Health r.Get("/health", healthHandler.Check) // Public: валидация лицензии r.Post("/api/v1/license/validate", licenseHandler.Validate) // Admin r.Group(func(r chi.Router) { r.Use(mw.AdminAuth(cfg.AdminAPIKey)) r.Post("/api/v1/admin/licenses", adminHandler.Create) r.Get("/api/v1/admin/licenses", adminHandler.List) r.Put("/api/v1/admin/licenses/{id}", adminHandler.Update) r.Delete("/api/v1/admin/licenses/{id}", adminHandler.Delete) r.Get("/api/v1/admin/licenses/{id}/audit", adminHandler.GetAuditLog) }) // === Server === addr := ":" + cfg.Port srv := &http.Server{Addr: addr, Handler: r} go func() { slog.Info("license server starting", "addr", addr) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { slog.Error("server error", "error", err) os.Exit(1) } }() // === Graceful shutdown === quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) sig := <-quit slog.Info("shutdown signal received", "signal", sig.String()) shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(shutdownCtx); err != nil { slog.Error("server shutdown error", "error", err) } slog.Info("closing database pool") pool.Close() slog.Info("closing redis client") redisClient.Close() slog.Info("server stopped gracefully") }