Files
FamilyHUB/backend/src/api/server.go
T

152 lines
4.1 KiB
Go

package api
import (
_ "FamilyHub/src/api/docs"
"FamilyHub/src/api/routers"
"FamilyHub/src/api/services"
"FamilyHub/src/config"
"FamilyHub/src/database"
"FamilyHub/src/integrations/ocr"
"FamilyHub/src/integrations/receiptProvider"
"FamilyHub/src/repositories"
"context"
"log"
"net/http"
"net/http/httptest"
"os"
"strings"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)
type Server struct {
httpServer *http.Server
ocr ocr.OCR
}
func NewServer(cfg config.Config) *Server {
dbManager := &database.Database{
ConnectionString: cfg.DBConnectionString,
MigrationsPath: "file://migrations",
}
dbConn, err := dbManager.Connect()
if err != nil {
log.Fatal(err)
}
if err := dbManager.RunMigrations(dbConn); err != nil {
log.Fatal(err)
}
if !cfg.DebugMode {
gin.SetMode(gin.ReleaseMode)
}
router := gin.New()
router.Use(gin.Logger())
//router.Use(requestLoggingMiddleware())
router.Use(gin.RecoveryWithWriter(os.Stderr))
if cfg.OpenAPIEnabled {
openAPIEndpoint := cfg.OpenAPIEndpoint
if openAPIEndpoint == "" {
openAPIEndpoint = "/openapi"
}
swaggerHandler := ginSwagger.WrapHandler(swaggerFiles.Handler)
serveSwaggerIndex := func(c *gin.Context) {
recorder := httptest.NewRecorder()
proxyCtx, _ := gin.CreateTestContext(recorder)
proxyCtx.Request = c.Request.Clone(c.Request.Context())
proxyCtx.Request.URL.Path = openAPIEndpoint + "/index.html"
proxyCtx.Request.RequestURI = openAPIEndpoint + "/index.html"
swaggerHandler(proxyCtx)
for key, values := range recorder.Header() {
for _, value := range values {
c.Writer.Header().Add(key, value)
}
}
body := strings.Replace(
recorder.Body.String(),
"<head>",
"<head><base href=\""+openAPIEndpoint+"/\">",
1,
)
c.Status(recorder.Code)
_, _ = c.Writer.WriteString(body)
}
router.GET(openAPIEndpoint, serveSwaggerIndex)
router.GET(openAPIEndpoint+"/*any", func(c *gin.Context) {
if c.Param("any") == "/" {
serveSwaggerIndex(c)
return
}
swaggerHandler(c)
})
}
apiV1 := router.Group("/api/v1")
transactionRepo := repositories.NewTransactionsSQLRepository(dbConn)
activityRepo := repositories.NewActivitySQLRepository(dbConn)
ocrSvc, err := ocr.NewGoogleOCR(context.Background())
if err != nil {
log.Fatal(err)
}
receiptRepo := repositories.NewReceiptsSQLRepository(dbConn)
receiptProvider_ := receiptProvider.NewReceiptProvider()
receiptService := services.NewReceiptService(receiptProvider_, receiptRepo, transactionRepo)
transactionService := services.NewTransactionService(transactionRepo, activityRepo)
transactionCreationService := services.NewTransactionCreationService(transactionService, receiptService, ocrSvc)
transactionRouter := routers.NewTransactionsRouter(transactionService, transactionCreationService)
transactionRouter.RegisterRoutes(apiV1)
activityService := services.NewActivityService(activityRepo)
activityRouter := routers.NewActivitiesRouter(activityService)
activityRouter.RegisterRoutes(apiV1)
usersRepo := repositories.NewUsersSQLRepository(dbConn)
usersService := services.NewUserService(usersRepo)
usersRouter := routers.NewUsersRouter(usersService)
usersRouter.RegisterRoutes(apiV1)
familyRepo := repositories.NewFamilySQLRepository(dbConn)
familyService := services.NewFamilyService(familyRepo)
familyRouter := routers.NewFamiliesRouter(familyService)
familyRouter.RegisterRoutes(apiV1)
otpRepo := repositories.NewOTPSQLRepository(dbConn)
authService := services.NewAuthService(usersRepo, otpRepo)
authRouter := routers.NewAuthRouter(authService)
authRouter.RegisterRouter(apiV1)
// подключаем статику Vue — должно быть последним
registerStaticFiles(router, "src/api/dist")
return &Server{
httpServer: &http.Server{
Addr: cfg.APIHost + ":" + cfg.APIPort,
Handler: router,
},
ocr: ocrSvc,
}
}
func (s *Server) Start() error {
return s.httpServer.ListenAndServe()
}
func (s *Server) Shutdown(ctx context.Context) error {
if s.ocr != nil {
_ = s.ocr.Close()
}
return s.httpServer.Shutdown(ctx)
}