Big Refacotr -part1

This commit is contained in:
PB
2025-10-27 14:01:25 +01:00
parent 44edb080d8
commit 5a304f11ac
46 changed files with 627 additions and 600 deletions

165
src/app/server.go Normal file
View File

@@ -0,0 +1,165 @@
package app
import (
"crypto/tls"
"log"
"net"
"time"
"github.com/go-redis/redis/v8"
jwt "github.com/gofiber/contrib/jwt"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgxpool"
commonDTO "git.ego.freeddns.org/egommerce/api-entities/common/dto"
cnf "git.ego.freeddns.org/egommerce/go-api-pkg/config"
"git.ego.freeddns.org/egommerce/identity-service/internal/http"
)
var defaultCORS = cors.New(
cors.Config{
// DEV CONFIG
AllowOrigins: "*",
AllowMethods: "GET, POST, PATCH, PUT, DELETE, OPTIONS",
AllowHeaders: "Accept, Authorization, Content-Type, Vary, X-Request-Id",
// PROD CONFIG
// AllowOrigins: "http://egommerce.io:3001", // client(reactjs) app url
// AllowCredentials: true,
// AllowMethods: "GET, POST, PATCH, PUT, DELETE",
},
)
type (
Server struct {
*fiber.App
ID string
addr string // e.g. "127.0.0.1:443"
plugins map[string]any
}
// HeaderRequestID struct {
// RequestID string `reqHeader:"x-request-id"`
// }
)
func NewServer(c *Config) *Server {
srv := &Server{
ID: c.ID,
App: fiber.New(fiber.Config{
AppName: c.ID,
ServerHeader: c.Name + ":" + c.ID,
ReadTimeout: c.ReadTimeout * time.Millisecond,
WriteTimeout: c.WriteTimeout * time.Millisecond,
IdleTimeout: c.IdleTimeout * time.Millisecond,
}),
addr: c.NetAddr,
plugins: make(map[string]any),
}
return srv
}
func (s *Server) Start() error {
s.setupMiddleware()
s.setupRouter()
crt, err := tls.LoadX509KeyPair("certs/identity-svc.crt", "certs/identity-svc.key")
if err != nil {
log.Fatal(err)
}
tlsCnf := &tls.Config{Certificates: []tls.Certificate{crt}}
ln, _ := net.Listen("tcp", s.addr)
ln = tls.NewListener(ln, tlsCnf)
return s.Listener(ln)
}
func (s *Server) OnShutdown() {
log.Printf("Server %s is going down...", s.ID)
s.getDatabase().Close()
s.getCache().Close()
s.Shutdown()
}
func (s *Server) addPlugin(name string, fn PluginFn) {
s.plugins[name] = fn()
}
// Plugin helper functions - using hardcoded keys because we rely on a specific implementation here...
func (s *Server) getCache() *redis.Client {
return (s.plugins["cache"]).(*redis.Client)
}
func (s *Server) getDatabase() *pgxpool.Pool {
return (s.plugins["database"]).(*pgxpool.Pool)
}
// func GetRequestID(c *fiber.Ctx) (string, error) {
// var hdr = new(HeaderRequestID)
// if err := c.ReqHeaderParser(hdr); err != nil {
// return "", err
// }
// return hdr.RequestID, nil
// }
func (s *Server) setupRouter() {
s.Options("*", defaultCORS)
s.Use(defaultCORS)
s.Get("/health", http.HealthHandlerFn(s.getDatabase(), s.getCache()))
s.Group("/v1").
Post("/login", http.LoginHandlerFn(s.getDatabase(), s.getCache())).
Post("/refresh", http.RefreshHandlerFn(s.getDatabase(), s.getCache())). // add JWTProtected() and get token from Auth Bearer header not from the body?
Post("/register", http.RegisterHandlerFn(s.getDatabase(), s.getCache())).
Get("/access", JWTProtected(), http.AccessHandlerFn(s.getDatabase(), s.getCache()))
}
func (s *Server) setupMiddleware() {
s.Use(LoggingMiddleware())
s.Use(XRequestIDMiddleware())
}
func LoggingMiddleware() func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
log.Printf("Request: %s, remote: %s, via: %s",
c.Request().URI().String(),
c.Context().RemoteIP().String(),
string(c.Context().UserAgent()),
)
return c.Next()
}
}
func XRequestIDMiddleware() func(c *fiber.Ctx) error {
return func(c *fiber.Ctx) error {
c.Set("X-Request-ID", uuid.New().String())
return c.Next()
}
}
func JWTProtected() func(c *fiber.Ctx) error {
secret := []byte(cnf.GetEnv("JWT_ACCESS_TOKEN_SECRET_KEY", "FallbackAccessTokenSecret"))
return jwt.New(jwt.Config{
SigningKey: jwt.SigningKey{Key: secret},
ContextKey: "jwt",
ErrorHandler: func(c *fiber.Ctx, err error) error {
return c.Status(fiber.StatusUnauthorized).JSON(commonDTO.ErrorResponseDTO{Error: "unauthorized"})
},
})
}
// func (s *Server) Error(c *fiber.Ctx, code int, msg string) error {
// return c.Status(code).JSON(dto.ErrorResponseDTO{Error: msg})
// }