saveinmed/backend-go/internal/server/server.go

92 lines
2.9 KiB
Go

package server
import (
"context"
"log"
"net/http"
"time"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/jmoiron/sqlx"
httpSwagger "github.com/swaggo/http-swagger"
"github.com/saveinmed/backend-go/internal/config"
"github.com/saveinmed/backend-go/internal/http/handler"
"github.com/saveinmed/backend-go/internal/http/middleware"
"github.com/saveinmed/backend-go/internal/payments"
"github.com/saveinmed/backend-go/internal/repository/postgres"
"github.com/saveinmed/backend-go/internal/usecase"
)
// Server wires the infrastructure and exposes HTTP handlers.
type Server struct {
cfg config.Config
db *sqlx.DB
mux *http.ServeMux
}
func New(cfg config.Config) (*Server, error) {
db, err := sqlx.Open("pgx", cfg.DatabaseURL)
if err != nil {
return nil, err
}
db.SetMaxOpenConns(cfg.MaxOpenConns)
db.SetMaxIdleConns(cfg.MaxIdleConns)
db.SetConnMaxIdleTime(cfg.ConnMaxIdle)
repo := postgres.New(db)
gateway := payments.NewMercadoPagoGateway()
svc := usecase.NewService(repo, gateway)
h := handler.New(svc)
mux := http.NewServeMux()
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("ok"))
})
mux.Handle("POST /api/companies", chain(http.HandlerFunc(h.CreateCompany), middleware.Logger, middleware.Gzip))
mux.Handle("GET /api/companies", chain(http.HandlerFunc(h.ListCompanies), middleware.Logger, middleware.Gzip))
mux.Handle("POST /api/products", chain(http.HandlerFunc(h.CreateProduct), middleware.Logger, middleware.Gzip))
mux.Handle("GET /api/products", chain(http.HandlerFunc(h.ListProducts), middleware.Logger, middleware.Gzip))
mux.Handle("POST /api/orders", chain(http.HandlerFunc(h.CreateOrder), middleware.Logger, middleware.Gzip))
mux.Handle("GET /api/orders/", chain(http.HandlerFunc(h.GetOrder), middleware.Logger, middleware.Gzip))
mux.Handle("PATCH /api/orders/", chain(http.HandlerFunc(h.UpdateOrderStatus), middleware.Logger, middleware.Gzip))
mux.Handle("POST /api/orders/", chain(http.HandlerFunc(h.CreatePaymentPreference), middleware.Logger, middleware.Gzip))
mux.Handle("GET /swagger/", httpSwagger.Handler(httpSwagger.URL("/swagger/doc.json")))
return &Server{cfg: cfg, db: db, mux: mux}, nil
}
// Start runs the HTTP server and ensures the database is reachable.
func (s *Server) Start(ctx context.Context) error {
if err := s.db.PingContext(ctx); err != nil {
return err
}
repo := postgres.New(s.db)
if err := repo.InitSchema(ctx); err != nil {
return err
}
srv := &http.Server{
Addr: s.cfg.Addr(),
Handler: s.mux,
ReadHeaderTimeout: 5 * time.Second,
}
log.Printf("starting %s on %s", s.cfg.AppName, s.cfg.Addr())
return srv.ListenAndServe()
}
func chain(h http.Handler, middlewareFns ...func(http.Handler) http.Handler) http.Handler {
for i := len(middlewareFns) - 1; i >= 0; i-- {
h = middlewareFns[i](h)
}
return h
}