feat: initial commit
This commit is contained in:
+148
@@ -0,0 +1,148 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"expvar"
|
||||
"log"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/FernandoVideira/LK_API_Temp/internal/auth"
|
||||
"github.com/FernandoVideira/LK_API_Temp/internal/db"
|
||||
"github.com/FernandoVideira/LK_API_Temp/internal/env"
|
||||
"github.com/FernandoVideira/LK_API_Temp/internal/mailer"
|
||||
"github.com/FernandoVideira/LK_API_Temp/internal/ratelimiter"
|
||||
"github.com/FernandoVideira/LK_API_Temp/internal/store"
|
||||
"github.com/FernandoVideira/LK_API_Temp/internal/store/cache"
|
||||
"github.com/go-redis/redis/v8"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const version = ""
|
||||
|
||||
// @title LK API Template
|
||||
// @description This is a template for building APIs with Go, Chi, and Swagger.
|
||||
// @termsOfService http://swagger.io/terms/
|
||||
|
||||
// @contact.name API Support
|
||||
// @contact.url http://www.swagger.io/support
|
||||
// @contact.email [email protected]
|
||||
|
||||
// @license.name Apache 2.0
|
||||
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
// @BasePath /v1
|
||||
//
|
||||
// @securityDefinitions.apikey ApiKeyAuth
|
||||
// @in header
|
||||
// @name Authorization
|
||||
// @description
|
||||
func main() {
|
||||
cfg := config{
|
||||
addr: env.GetString("ADDR", ":8080"),
|
||||
apiURL: env.GetString("EXTERNAL_URL", "localhost:8080"),
|
||||
frontEndURL: env.GetString("FRONTEND_URL", "http://localhost:5173"),
|
||||
db: dbConfig{
|
||||
addr: env.GetString("DB_ADDR", "postgres://postgres:postgres@localhost:5432/lk_tmpl?sslmode=disable"),
|
||||
maxOpenConns: env.GetInt("DB_MAX_OPEN_CONNS", 30),
|
||||
maxIdleConns: env.GetInt("DB_MAX_IDLE_CONNS", 30),
|
||||
maxIdleTime: env.GetDuration("DB_MAX_IDLE_TIME", "15m"),
|
||||
},
|
||||
redisCfg: redisConfig{
|
||||
addr: env.GetString("REDIS_ADDR", "localhost:6379"),
|
||||
pw: env.GetString("REDIS_PASSWORD", ""),
|
||||
db: env.GetInt("REDIS_DB", 0),
|
||||
enabled: env.GetBool("REDIS_ENABLED", false),
|
||||
},
|
||||
env: env.GetString("ENV", "development"),
|
||||
mail: mailConfig{
|
||||
exp: time.Hour * 24 * 3,
|
||||
fromEmail: env.GetString("FROM_EMAIL", ""),
|
||||
sendGrid: sendGridConfig{
|
||||
apiKey: env.GetString("SENDGRID_API_KEY", ""),
|
||||
},
|
||||
},
|
||||
auth: authConfig{
|
||||
basic: basicConfig{
|
||||
username: env.GetString("BASIC_AUTH_USERNAME", "admin"),
|
||||
password: env.GetString("BASIC_AUTH_PASSWORD", "admin"),
|
||||
},
|
||||
token: tokenConfig{
|
||||
secret: env.GetString("AUTH_TOKEN_SECRET", "secret"),
|
||||
exp: env.GetDuration("AUTH_TOKEN_EXP", "24h"),
|
||||
iss: env.GetString("AUTH_TOKEN_ISS", "lkapi"),
|
||||
aud: env.GetString("AUTH_TOKEN_AUD", "lkapi"),
|
||||
},
|
||||
},
|
||||
rateLimiter: ratelimiter.Config{
|
||||
RequestsPerTimeFrame: env.GetInt("RATE_LIMITER_REQS_COUNT", 20),
|
||||
TimeFrame: env.GetDuration("RATE_LIMITER_TIME_FRAME", "1m"),
|
||||
Enabled: env.GetBool("RATE_LIMITER_ENABLED", true),
|
||||
},
|
||||
}
|
||||
|
||||
// Logger
|
||||
logger := zap.Must(zap.NewProduction()).Sugar()
|
||||
defer logger.Sync()
|
||||
|
||||
// Database
|
||||
db, err := db.New(
|
||||
cfg.db.addr,
|
||||
cfg.db.maxOpenConns,
|
||||
cfg.db.maxIdleConns,
|
||||
cfg.db.maxIdleTime,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
logger.Info("database connection established")
|
||||
|
||||
// Cache
|
||||
var redisDb *redis.Client
|
||||
if cfg.redisCfg.enabled {
|
||||
redisDb = cache.NewRedisClient(cfg.redisCfg.addr, cfg.redisCfg.pw, cfg.redisCfg.db)
|
||||
logger.Info("redis connection established")
|
||||
}
|
||||
|
||||
// Rate Limiter
|
||||
rateLimiter := ratelimiter.NewFixedWindowLimiter(
|
||||
cfg.rateLimiter.RequestsPerTimeFrame,
|
||||
cfg.rateLimiter.TimeFrame,
|
||||
)
|
||||
|
||||
store := store.NewStorage(db)
|
||||
cacheStorage := cache.NewRedisStorage(redisDb)
|
||||
mailer := mailer.NewSendGrid(cfg.mail.sendGrid.apiKey, cfg.mail.fromEmail)
|
||||
|
||||
jwtAuthenticator := auth.NewJWTAuthenticator(
|
||||
cfg.auth.token.secret,
|
||||
cfg.auth.token.aud,
|
||||
cfg.auth.token.iss,
|
||||
)
|
||||
|
||||
api := api{
|
||||
config: cfg,
|
||||
store: store,
|
||||
cacheStore: cacheStorage,
|
||||
logger: logger,
|
||||
mailer: mailer,
|
||||
authenticator: jwtAuthenticator,
|
||||
rateLimiter: rateLimiter,
|
||||
}
|
||||
|
||||
// Metrics Collected
|
||||
expvar.NewString("version").Set(version)
|
||||
expvar.Publish("database", expvar.Func(func() any {
|
||||
return db.Stats()
|
||||
}))
|
||||
expvar.Publish("redis", expvar.Func(func() any {
|
||||
return redisDb.Info(context.Background(), "keyspace")
|
||||
}))
|
||||
expvar.Publish("goroutines", expvar.Func(func() any {
|
||||
return runtime.NumGoroutine()
|
||||
}))
|
||||
|
||||
mux := api.mount()
|
||||
log.Fatal(api.run(mux))
|
||||
}
|
||||
Reference in New Issue
Block a user