From 85b53cf6734d0038bef6f0ce7f797bafc749d31c Mon Sep 17 00:00:00 2001 From: SShlykov Date: Sat, 11 May 2024 00:38:20 +0300 Subject: [PATCH] feat: changed controllers --- .../http/endpoint/web_server.go | 0 .../http/middleware/metrics.go | 0 .../http/middleware/middleware.go | 0 .../http/v1/router => app/http/v1}/const.go | 4 +- .../http/v1/images/controller.go} | 35 ++++-------- .../errors => app/http/v1/images}/errors.go | 2 +- procima/internal/app/http/v1/images/routes.go | 10 ++++ procima/internal/app/http/v1/images/utils.go | 15 +++++ .../app/http/v1/metrics/controller.go | 31 ++++++++++ .../internal/app/http/v1/metrics/routes.go | 10 ++++ procima/internal/bootstrap/app/app.go | 5 +- .../internal/bootstrap/registry/web_server.go | 54 ++++++++---------- .../controller/mocks/mock_image_controller.go | 52 ----------------- .../v1/controller/mocks/mock_image_service.go | 56 ------------------- .../http/v1/router/image_router.go | 21 ------- .../integration/http/v1/router/metrics.go | 29 ---------- 16 files changed, 106 insertions(+), 218 deletions(-) rename procima/internal/{integration => app}/http/endpoint/web_server.go (100%) rename procima/internal/{integration => app}/http/middleware/metrics.go (100%) rename procima/internal/{integration => app}/http/middleware/middleware.go (100%) rename procima/internal/{integration/http/v1/router => app/http/v1}/const.go (72%) rename procima/internal/{integration/http/v1/controller/image.go => app/http/v1/images/controller.go} (63%) rename procima/internal/{integration/http/v1/errors => app/http/v1/images}/errors.go (92%) create mode 100644 procima/internal/app/http/v1/images/routes.go create mode 100644 procima/internal/app/http/v1/images/utils.go create mode 100644 procima/internal/app/http/v1/metrics/controller.go create mode 100644 procima/internal/app/http/v1/metrics/routes.go delete mode 100644 procima/internal/integration/http/v1/controller/mocks/mock_image_controller.go delete mode 100644 procima/internal/integration/http/v1/controller/mocks/mock_image_service.go delete mode 100644 procima/internal/integration/http/v1/router/image_router.go delete mode 100644 procima/internal/integration/http/v1/router/metrics.go diff --git a/procima/internal/integration/http/endpoint/web_server.go b/procima/internal/app/http/endpoint/web_server.go similarity index 100% rename from procima/internal/integration/http/endpoint/web_server.go rename to procima/internal/app/http/endpoint/web_server.go diff --git a/procima/internal/integration/http/middleware/metrics.go b/procima/internal/app/http/middleware/metrics.go similarity index 100% rename from procima/internal/integration/http/middleware/metrics.go rename to procima/internal/app/http/middleware/metrics.go diff --git a/procima/internal/integration/http/middleware/middleware.go b/procima/internal/app/http/middleware/middleware.go similarity index 100% rename from procima/internal/integration/http/middleware/middleware.go rename to procima/internal/app/http/middleware/middleware.go diff --git a/procima/internal/integration/http/v1/router/const.go b/procima/internal/app/http/v1/const.go similarity index 72% rename from procima/internal/integration/http/v1/router/const.go rename to procima/internal/app/http/v1/const.go index 891979a..1181f72 100644 --- a/procima/internal/integration/http/v1/router/const.go +++ b/procima/internal/app/http/v1/const.go @@ -1,7 +1,7 @@ -package router +package v1 const ( - MetricsURL = "/api/metrics" + MetricsURL = "/metrics" BaseURL = "/api/v1" ImageURL = "/images" ImageUploadURL = ImageURL + UPLOAD diff --git a/procima/internal/integration/http/v1/controller/image.go b/procima/internal/app/http/v1/images/controller.go similarity index 63% rename from procima/internal/integration/http/v1/controller/image.go rename to procima/internal/app/http/v1/images/controller.go index ffc9175..d767e01 100644 --- a/procima/internal/integration/http/v1/controller/image.go +++ b/procima/internal/app/http/v1/images/controller.go @@ -1,27 +1,26 @@ -package controller +package images import ( "context" errorsPkg "errors" "github.com/SShlykov/procima/procima/internal/domain/services" - "github.com/SShlykov/procima/procima/internal/integration/http/v1/errors" "github.com/SShlykov/procima/procima/internal/models" loggerPkg "github.com/SShlykov/procima/procima/pkg/logger" "github.com/gin-gonic/gin" "net/http" - "regexp" ) // ImageController контроллер для обработки изображений // -//go:generate mockgen -destination=./mocks/mock_image_controller.go -package=mocks github.com/SShlykov/procima/procima/internal/integration/http/v1/controller ImageController +//go:generate mockgen -destination=./mocks/mock_image_controller.go -package=mocks github.com/SShlykov/procima/procima/internal/app/http/v1/controller ImageController type ImageController interface { + RegisterRoutes(router *gin.RouterGroup) ProcessImage(c *gin.Context) } // ImageService сервис для обработки изображений // -//go:generate mockgen -destination=./mocks/mock_image_service.go -package=mocks github.com/SShlykov/procima/procima/internal/integration/http/v1/controller ImageService +//go:generate mockgen -destination=./mocks/mock_image_service.go -package=mocks github.com/SShlykov/procima/procima/internal/app/http/v1/controller ImageService type ImageService interface { ProcessImage(ctx context.Context, request models.RequestImage) (*[]byte, error) } @@ -42,21 +41,21 @@ func (ic *imageController) ProcessImage(c *gin.Context) { var request models.RequestImage if err := c.BindJSON(&request); err != nil { - ic.logger.Error(errors.ErrorBadRequest, loggerPkg.Err(err)) - c.JSON(http.StatusBadRequest, gin.H{"error": errors.ErrorBadRequest}) + ic.logger.Error(ErrorBadRequest, loggerPkg.Err(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": ErrorBadRequest}) return } if len(request.Image) > ic.fileSizeLimit { - ic.logger.Error(errors.ErrorBadRequest, loggerPkg.String("error", errors.ErrorExcededFileSize)) - c.JSON(http.StatusBadRequest, gin.H{"error": errors.ErrorExcededFileSize, "limit": ic.fileSizeLimit, "actual": len(request.Image)}) + ic.logger.Error(ErrorBadRequest, loggerPkg.String("error", ErrorExcededFileSize)) + c.JSON(http.StatusBadRequest, gin.H{"error": ErrorExcededFileSize, "limit": ic.fileSizeLimit, "actual": len(request.Image)}) return } imageType, found := getImageType(request.Image) if !found || !ic.isAvailable(imageType) { - ic.logger.Error(errors.ErrorBadRequest, loggerPkg.String("error", errors.ErrorInvalidImageType)) - c.JSON(http.StatusBadRequest, gin.H{"error": errors.ErrorInvalidImageType, "available": ic.availableImageTypes, "actual": imageType}) + ic.logger.Error(ErrorBadRequest, loggerPkg.String("error", ErrorInvalidImageType)) + c.JSON(http.StatusBadRequest, gin.H{"error": ErrorInvalidImageType, "available": ic.availableImageTypes, "actual": imageType}) return } @@ -68,7 +67,7 @@ func (ic *imageController) ProcessImage(c *gin.Context) { return } - c.JSON(http.StatusInternalServerError, gin.H{"error": errors.ErrorInternal}) + c.JSON(http.StatusInternalServerError, gin.H{"error": ErrorInternal}) return } @@ -85,15 +84,3 @@ func (ic *imageController) isAvailable(imageType string) bool { } return false } - -const PartsWhenImage = 2 - -func getImageType(dataURL string) (string, bool) { - re := regexp.MustCompile(`^data:image/([^;]+);base64,`) - matches := re.FindStringSubmatch(dataURL[:50]) - - if len(matches) == PartsWhenImage { - return matches[1], true - } - return "", false -} diff --git a/procima/internal/integration/http/v1/errors/errors.go b/procima/internal/app/http/v1/images/errors.go similarity index 92% rename from procima/internal/integration/http/v1/errors/errors.go rename to procima/internal/app/http/v1/images/errors.go index 5964ae7..4a37807 100644 --- a/procima/internal/integration/http/v1/errors/errors.go +++ b/procima/internal/app/http/v1/images/errors.go @@ -1,4 +1,4 @@ -package errors +package images const ( ErrorBadRequest = "bad request" diff --git a/procima/internal/app/http/v1/images/routes.go b/procima/internal/app/http/v1/images/routes.go new file mode 100644 index 0000000..bc9fe70 --- /dev/null +++ b/procima/internal/app/http/v1/images/routes.go @@ -0,0 +1,10 @@ +package images + +import ( + v1 "github.com/SShlykov/procima/procima/internal/app/http/v1" + "github.com/gin-gonic/gin" +) + +func (ic *imageController) RegisterRoutes(router *gin.RouterGroup) { + router.POST(v1.ImageUploadURL, ic.ProcessImage) +} diff --git a/procima/internal/app/http/v1/images/utils.go b/procima/internal/app/http/v1/images/utils.go new file mode 100644 index 0000000..77c04e7 --- /dev/null +++ b/procima/internal/app/http/v1/images/utils.go @@ -0,0 +1,15 @@ +package images + +import "regexp" + +const PartsWhenImage = 2 + +func getImageType(dataURL string) (string, bool) { + re := regexp.MustCompile(`^data:image/([^;]+);base64,`) + matches := re.FindStringSubmatch(dataURL[:50]) + + if len(matches) == PartsWhenImage { + return matches[1], true + } + return "", false +} diff --git a/procima/internal/app/http/v1/metrics/controller.go b/procima/internal/app/http/v1/metrics/controller.go new file mode 100644 index 0000000..0873397 --- /dev/null +++ b/procima/internal/app/http/v1/metrics/controller.go @@ -0,0 +1,31 @@ +package metrics + +import ( + "github.com/SShlykov/procima/procima/pkg/metrics" + "github.com/gin-gonic/gin" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" +) + +type Controller interface { + PrometheusHandler(c *gin.Context) + RegisterRoutes(router *gin.RouterGroup) +} + +type metricsController struct { + metr metrics.Metrics +} + +func NewMetricsController(metr metrics.Metrics) Controller { + return &metricsController{metr: metr} +} + +func (mc *metricsController) PrometheusHandler(c *gin.Context) { + reg := prometheus.NewRegistry() + + mc.metr.Register(reg) + + h := promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg}) + + h.ServeHTTP(c.Writer, c.Request) +} diff --git a/procima/internal/app/http/v1/metrics/routes.go b/procima/internal/app/http/v1/metrics/routes.go new file mode 100644 index 0000000..d9a13e5 --- /dev/null +++ b/procima/internal/app/http/v1/metrics/routes.go @@ -0,0 +1,10 @@ +package metrics + +import ( + v1 "github.com/SShlykov/procima/procima/internal/app/http/v1" + "github.com/gin-gonic/gin" +) + +func (mc *metricsController) RegisterRoutes(router *gin.RouterGroup) { + router.POST(v1.ImageUploadURL, mc.PrometheusHandler) +} diff --git a/procima/internal/bootstrap/app/app.go b/procima/internal/bootstrap/app/app.go index d93e8a7..3bed169 100644 --- a/procima/internal/bootstrap/app/app.go +++ b/procima/internal/bootstrap/app/app.go @@ -5,6 +5,7 @@ import ( "github.com/SShlykov/procima/procima/internal/bootstrap/registry" configPkg "github.com/SShlykov/procima/procima/internal/config" "github.com/SShlykov/procima/procima/internal/domain/processor" + "github.com/SShlykov/procima/procima/internal/domain/services" loggerPkg "github.com/SShlykov/procima/procima/pkg/logger" "github.com/SShlykov/procima/procima/pkg/metrics" "os/signal" @@ -52,14 +53,16 @@ func (app *App) Run() error { app.logger.Info("запуск приложения", loggerPkg.Any("cfg", app.config)) app.logger.Debug("включены отладочные сообщения") + imageProcessorChan := make(chan processor.ImageProcessorItem) + service := services.NewImageService(app.logger, imageProcessorChan) wg.Add(1) go func() { defer wg.Done() defer app.cancel() defer app.logger.Info(app.config.AppName + " остановлен") - server, err := registry.InitWebServer(app.logger, app.configPath, app.metric, imageProcessorChan) + server, err := registry.InitWebServer(app.logger, app.configPath, app.metric, service) if err != nil { app.logger.Error("failed to init web server", loggerPkg.Err(err)) return diff --git a/procima/internal/bootstrap/registry/web_server.go b/procima/internal/bootstrap/registry/web_server.go index 4ab96f4..e7ff98d 100644 --- a/procima/internal/bootstrap/registry/web_server.go +++ b/procima/internal/bootstrap/registry/web_server.go @@ -2,20 +2,20 @@ package registry import ( "errors" + "github.com/SShlykov/procima/procima/internal/app/http/endpoint" + "github.com/SShlykov/procima/procima/internal/app/http/middleware" + v1 "github.com/SShlykov/procima/procima/internal/app/http/v1" + cntr "github.com/SShlykov/procima/procima/internal/app/http/v1/images" + metrics2 "github.com/SShlykov/procima/procima/internal/app/http/v1/metrics" "github.com/SShlykov/procima/procima/internal/config" - "github.com/SShlykov/procima/procima/internal/domain/processor" "github.com/SShlykov/procima/procima/internal/domain/services" - "github.com/SShlykov/procima/procima/internal/integration/http/endpoint" - cntr "github.com/SShlykov/procima/procima/internal/integration/http/v1/controller" - "github.com/SShlykov/procima/procima/internal/integration/http/v1/router" loggerPkg "github.com/SShlykov/procima/procima/pkg/logger" "github.com/SShlykov/procima/procima/pkg/metrics" "github.com/gin-gonic/gin" "net/http" ) -func InitWebServer(logger loggerPkg.Logger, configPath string, metr metrics.Metrics, - processorChan chan<- processor.ImageProcessorItem) (*endpoint.WebServer, error) { +func InitWebServer(logger loggerPkg.Logger, configPath string, metr metrics.Metrics, imgService services.ImageService) (*endpoint.WebServer, error) { cfg, err := config.LoadServerConfig(configPath) if err != nil { return nil, errors.New("failed to load server config: " + err.Error()) @@ -24,40 +24,30 @@ func InitWebServer(logger loggerPkg.Logger, configPath string, metr metrics.Metr gin.SetMode(gin.ReleaseMode) engine := gin.New() engine.Use(gin.Recovery()) + engine.Use(middleware.Metrics(logger, metr)) + group := engine.Group(v1.BaseURL) - SetRouter(engine, logger, cfg, metr, processorChan) + metrContr := metrics2.NewMetricsController(metr) + metrContr.RegisterRoutes(group) + imgCntr := cntr.NewImageController(imgService, logger, cfg.AvailableTypes, cfg.MaxFileSize) + imgCntr.RegisterRoutes(group) + + webSever := configToWebServer(cfg) + webSever.Server.Handler = engine + + return webSever, nil +} + +func configToWebServer(cfg *config.ServerConfig) *endpoint.WebServer { srv := &http.Server{ ReadHeaderTimeout: cfg.ReadHeaderTimeout, ReadTimeout: cfg.ReadTimeout, WriteTimeout: cfg.WriteTimeout, IdleTimeout: cfg.IddleTimeout, - Addr: cfg.Addr, - Handler: engine, + Addr: cfg.Addr, } - return &endpoint.WebServer{Server: srv, Config: cfg}, nil -} - -func SetRouter(engine *gin.Engine, logger loggerPkg.Logger, serverConfig *config.ServerConfig, metr metrics.Metrics, - processorChan chan<- processor.ImageProcessorItem) { - imageController := initImageController(logger, serverConfig, processorChan) - - routers := - []func(engine *gin.Engine, logger loggerPkg.Logger){ - router.ImageRouter(imageController, metr), - router.MetricsRouter(metr), - } - - for _, routes := range routers { - routes(engine, logger) - } -} - -func initImageController(logger loggerPkg.Logger, serverConfig *config.ServerConfig, - processorChan chan<- processor.ImageProcessorItem) cntr.ImageController { - service := services.NewImageService(logger, processorChan) - controller := cntr.NewImageController(service, logger, serverConfig.AvailableTypes, serverConfig.MaxFileSize) - return controller + return &endpoint.WebServer{Server: srv, Config: cfg} } diff --git a/procima/internal/integration/http/v1/controller/mocks/mock_image_controller.go b/procima/internal/integration/http/v1/controller/mocks/mock_image_controller.go deleted file mode 100644 index 520ec01..0000000 --- a/procima/internal/integration/http/v1/controller/mocks/mock_image_controller.go +++ /dev/null @@ -1,52 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/SShlykov/procima/procima/internal/integration/http/v1/controller (interfaces: ImageController) -// -// Generated by this command: -// -// mockgen -destination=./mocks/mock_image_controller.go -package=mocks github.com/SShlykov/procima/procima/internal/integration/http/v1/controller ImageController -// - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - gin "github.com/gin-gonic/gin" - gomock "go.uber.org/mock/gomock" -) - -// MockImageController is a mock of ImageController interface. -type MockImageController struct { - ctrl *gomock.Controller - recorder *MockImageControllerMockRecorder -} - -// MockImageControllerMockRecorder is the mock recorder for MockImageController. -type MockImageControllerMockRecorder struct { - mock *MockImageController -} - -// NewMockImageController creates a new mock instance. -func NewMockImageController(ctrl *gomock.Controller) *MockImageController { - mock := &MockImageController{ctrl: ctrl} - mock.recorder = &MockImageControllerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockImageController) EXPECT() *MockImageControllerMockRecorder { - return m.recorder -} - -// ProcessImage mocks base method. -func (m *MockImageController) ProcessImage(arg0 *gin.Context) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "ProcessImage", arg0) -} - -// ProcessImage indicates an expected call of ProcessImage. -func (mr *MockImageControllerMockRecorder) ProcessImage(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessImage", reflect.TypeOf((*MockImageController)(nil).ProcessImage), arg0) -} diff --git a/procima/internal/integration/http/v1/controller/mocks/mock_image_service.go b/procima/internal/integration/http/v1/controller/mocks/mock_image_service.go deleted file mode 100644 index f28a83d..0000000 --- a/procima/internal/integration/http/v1/controller/mocks/mock_image_service.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/SShlykov/procima/procima/internal/integration/http/v1/controller (interfaces: ImageService) -// -// Generated by this command: -// -// mockgen -destination=./mocks/mock_image_service.go -package=mocks github.com/SShlykov/procima/procima/internal/integration/http/v1/controller ImageService -// - -// Package mocks is a generated GoMock package. -package mocks - -import ( - context "context" - reflect "reflect" - - models "github.com/SShlykov/procima/procima/internal/models" - gomock "go.uber.org/mock/gomock" -) - -// MockImageService is a mock of ImageService interface. -type MockImageService struct { - ctrl *gomock.Controller - recorder *MockImageServiceMockRecorder -} - -// MockImageServiceMockRecorder is the mock recorder for MockImageService. -type MockImageServiceMockRecorder struct { - mock *MockImageService -} - -// NewMockImageService creates a new mock instance. -func NewMockImageService(ctrl *gomock.Controller) *MockImageService { - mock := &MockImageService{ctrl: ctrl} - mock.recorder = &MockImageServiceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockImageService) EXPECT() *MockImageServiceMockRecorder { - return m.recorder -} - -// ProcessImage mocks base method. -func (m *MockImageService) ProcessImage(arg0 context.Context, arg1 models.RequestImage) (*[]byte, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ProcessImage", arg0, arg1) - ret0, _ := ret[0].(*[]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ProcessImage indicates an expected call of ProcessImage. -func (mr *MockImageServiceMockRecorder) ProcessImage(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessImage", reflect.TypeOf((*MockImageService)(nil).ProcessImage), arg0, arg1) -} diff --git a/procima/internal/integration/http/v1/router/image_router.go b/procima/internal/integration/http/v1/router/image_router.go deleted file mode 100644 index 3492940..0000000 --- a/procima/internal/integration/http/v1/router/image_router.go +++ /dev/null @@ -1,21 +0,0 @@ -package router - -import ( - "github.com/SShlykov/procima/procima/internal/integration/http/middleware" - loggerPkg "github.com/SShlykov/procima/procima/pkg/logger" - "github.com/SShlykov/procima/procima/pkg/metrics" - "github.com/gin-gonic/gin" -) - -type ImageController interface { - ProcessImage(c *gin.Context) -} - -func ImageRouter(controller ImageController, metr metrics.Metrics) func(engine *gin.Engine, logger loggerPkg.Logger) { - return func(engine *gin.Engine, logger loggerPkg.Logger) { - group := engine.Group(BaseURL) - group.Use(middleware.Metrics(logger, metr)) - - group.POST(ImageUploadURL, controller.ProcessImage) - } -} diff --git a/procima/internal/integration/http/v1/router/metrics.go b/procima/internal/integration/http/v1/router/metrics.go deleted file mode 100644 index 68300be..0000000 --- a/procima/internal/integration/http/v1/router/metrics.go +++ /dev/null @@ -1,29 +0,0 @@ -package router - -import ( - loggerPkg "github.com/SShlykov/procima/procima/pkg/logger" - "github.com/SShlykov/procima/procima/pkg/metrics" - "github.com/gin-gonic/gin" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -func MetricsRouter(metr metrics.Metrics) func(engine *gin.Engine, logger loggerPkg.Logger) { - return func(engine *gin.Engine, _ loggerPkg.Logger) { - group := engine.Group(MetricsURL) - - group.GET("", prometheusHandler(metr)) - } -} - -func prometheusHandler(metr metrics.Metrics) gin.HandlerFunc { - reg := prometheus.NewRegistry() - - metr.Register(reg) - - h := promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg}) - - return func(c *gin.Context) { - h.ServeHTTP(c.Writer, c.Request) - } -}