package link import ( "encoding/json" "github.com/jackc/pgx/v4/pgxpool" "github.com/labstack/echo/v4" "net/http" "net/url" "strconv" ) func redirectHandler(ctx echo.Context, serv Service) error { linkId := ctx.Param("id") link, err := serv.GetById(linkId) if err != nil { return err } return ctx.Redirect(http.StatusSeeOther, link.RedirectURL.String()) } func creationHandler(ctx echo.Context, serv Service) error { var model CreationModel if err := json.NewDecoder(ctx.Request().Body).Decode(&model); err != nil { return echo.NewHTTPError(http.StatusBadRequest, "Invalid data format.") } entity, err := model.MapModelToEntity() if err != nil { return echo.NewHTTPError(http.StatusBadRequest, "Invalid URL.") } if err = serv.Create(entity); err != nil { return err } return ctx.NoContent(http.StatusCreated) } func retrievalByIdHandler(ctx echo.Context, serv Service) error { linkId := ctx.Param("id") l, err := serv.GetById(linkId) if err != nil { return err } return ctx.JSON(http.StatusOK, MapEntityToModel(l)) } func allRetrievalHandler(ctx echo.Context, serv Service) error { limit := 20 if v := ctx.QueryParam("limit"); v != "" { num, err := strconv.Atoi(v) if err != nil || num < 0 { return echo.NewHTTPError(http.StatusBadRequest, "Invalid limit value.") } limit = num } offset := 0 if v := ctx.QueryParam("offset"); v != "" { num, err := strconv.Atoi(v) if err != nil || num < 0 { return echo.NewHTTPError(http.StatusBadRequest, "Invalid offset value.") } offset = num } links, err := serv.GetAll(limit, offset) if err != nil { return err } models := make([]ResourceModel, len(links)) for i, v := range links { models[i] = MapEntityToModel(v) } return ctx.JSON(http.StatusOK, models) } func updateHandler(ctx echo.Context, serv Service) error { linkId := ctx.Param("id") var model UpdateModel if err := json.NewDecoder(ctx.Request().Body).Decode(&model); err != nil { return echo.NewHTTPError(http.StatusBadRequest, "Invalid data format.") } updatingLink, err := serv.GetById(linkId) if err != nil { return err } hasChanges := false switch { case model.Name != "" && model.Name != updatingLink.Name: updatingLink.Name = model.Name hasChanges = true case model.RedirectURL != "" && model.RedirectURL != updatingLink.RedirectURL.String(): if parsedUrl, err := url.Parse(model.RedirectURL); err != nil { return echo.NewHTTPError(http.StatusBadRequest, "Invalid URL value.") } else { updatingLink.RedirectURL = *parsedUrl } hasChanges = true } if hasChanges { if err = serv.Update(updatingLink); err != nil { return err } } return ctx.NoContent(http.StatusOK) } func removalHandler(ctx echo.Context, serv Service) error { linkId := ctx.Param("id") if err := serv.DeleteById(linkId); err != nil { return err } return ctx.NoContent(http.StatusNoContent) } func AddHandlers(server *echo.Echo, pool *pgxpool.Pool) { serv := NewService(NewRepository(pool)) linksGroup := server.Group("/links") exactLinkGroup := linksGroup.Group("/:id") linksGroup.POST("", func(ctx echo.Context) error { return creationHandler(ctx, serv) }) linksGroup.GET("", func(ctx echo.Context) error { return allRetrievalHandler(ctx, serv) }) exactLinkGroup.GET("", func(ctx echo.Context) error { return retrievalByIdHandler(ctx, serv) }) exactLinkGroup.PATCH("", func(ctx echo.Context) error { return updateHandler(ctx, serv) }) exactLinkGroup.DELETE("", func(ctx echo.Context) error { return removalHandler(ctx, serv) }) server.GET("/:id", func(ctx echo.Context) error { return redirectHandler(ctx, serv) }) }