Skip to content

Commit

Permalink
feat: changed controllers
Browse files Browse the repository at this point in the history
  • Loading branch information
SShlykov committed May 10, 2024
1 parent cb0a9fa commit 85b53cf
Show file tree
Hide file tree
Showing 16 changed files with 106 additions and 218 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package router
package v1

const (
MetricsURL = "/api/metrics"
MetricsURL = "/metrics"
BaseURL = "/api/v1"
ImageURL = "/images"
ImageUploadURL = ImageURL + UPLOAD
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
Expand All @@ -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
}

Expand All @@ -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
}

Expand All @@ -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
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package errors
package images

const (
ErrorBadRequest = "bad request"
Expand Down
10 changes: 10 additions & 0 deletions procima/internal/app/http/v1/images/routes.go
Original file line number Diff line number Diff line change
@@ -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)
}
15 changes: 15 additions & 0 deletions procima/internal/app/http/v1/images/utils.go
Original file line number Diff line number Diff line change
@@ -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
}
31 changes: 31 additions & 0 deletions procima/internal/app/http/v1/metrics/controller.go
Original file line number Diff line number Diff line change
@@ -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)
}
10 changes: 10 additions & 0 deletions procima/internal/app/http/v1/metrics/routes.go
Original file line number Diff line number Diff line change
@@ -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)
}
5 changes: 4 additions & 1 deletion procima/internal/bootstrap/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
54 changes: 22 additions & 32 deletions procima/internal/bootstrap/registry/web_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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}
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit 85b53cf

Please sign in to comment.