From ae2fe39c79c75ebb72d298c243c0f684e64d5cd4 Mon Sep 17 00:00:00 2001 From: truongtop1 Date: Fri, 9 Aug 2024 00:31:58 +0700 Subject: [PATCH] chore: refactor code & update deps --- api/Dockerfile | 4 +- api/database/database.go | 16 +++---- api/go.mod | 22 +++++----- api/go.sum | 44 +++++++++---------- api/helpers/constant.go | 34 +++++++++++++++ api/helpers/helpers.go | 18 +++----- api/main.go | 34 +++++---------- api/routes/resolve.go | 15 ++++--- api/routes/shorten.go | 91 ++++++++++++++++++++------------------- api/routes/statistical.go | 28 ++++++++---- 10 files changed, 168 insertions(+), 138 deletions(-) create mode 100644 api/helpers/constant.go diff --git a/api/Dockerfile b/api/Dockerfile index abde840..9febf2d 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -19,8 +19,8 @@ LABEL "org.opencontainers.image.authors"="Tran Nguyen Thuong Truong 0 { - // limit, _ := r2.TTL(database.Ctx, c.IP()).Result() - // return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error":"rate limit exceeded", "retry_after": limit / time.Second}) - // } - // } + val, err := r2.Get(helpers.Ctx, c.IP()).Result() + if err == redis.Nil { + _ = r2.Set(helpers.Ctx, c.IP(), os.Getenv("API_QUOTA"), 1*time.Second).Err() + } else { + val, _ = r2.Get(helpers.Ctx, c.IP()).Result() + valInt, _ := strconv.Atoi(val) + if valInt > 0 { + limit, _ := r2.TTL(helpers.Ctx, c.IP()).Result() + return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error": fmt.Sprintf("rate limit exceeded, retry_after: %d", limit/time.Nanosecond/time.Second)}) + } + } if !govalidator.IsURL(body.URL) { - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error":"invalid URL"}) + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": helpers.INVALID_URL}) } if !helpers.RemoveDomainError(body.URL) { - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error":"cannot shorten this URL"}) + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": helpers.CANNOT_SHORTEN_URL}) } body.URL = helpers.EnforceHTTP(body.URL) var id string - if body.CustomShort == ""{ + if body.CustomShort == "" { id = uuid.New().String()[:6] - }else { + } else { id = body.CustomShort } r := database.CreateClient(0) defer r.Close() - val, _ = r.Get(database.Ctx, id).Result() + val, _ = r.Get(helpers.Ctx, id).Result() if val != "" { - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error":"short link already exists"}) + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": helpers.SHORT_LINK_EXISTS}) } if body.Expiry == 0 { body.Expiry = 24 } - err = r.Set(database.Ctx, id, body.URL, body.Expiry*3600*time.Second).Err() + err = r.Set(helpers.Ctx, id, body.URL, body.Expiry*3600*time.Second).Err() if err != nil { - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error":"cannot connect to database"}) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": helpers.CANNOT_CONNECT_TO_DB}) } // add shorted url to index - err = r.SAdd(database.Ctx, "index:" + body.IP, id).Err() + err = r.SAdd(helpers.Ctx, helpers.INDEX+body.IP, id).Err() if err != nil { - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error":"cannot connect to database"}) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": helpers.CANNOT_CONNECT_TO_DB}) } - resp := Response { - URL: body.URL, - CustomShort: "", - Expiry: body.Expiry, - XRateRemaining: 10, + resp := Response{ + URL: body.URL, + CustomShort: "", + Expiry: body.Expiry, + XRateRemaining: 10, XRateLimitReset: 30, } - r2.Decr(database.Ctx, c.IP()) + r2.Decr(helpers.Ctx, c.IP()) - val, _ = r2.Get(database.Ctx, c.IP()).Result() + val, _ = r2.Get(helpers.Ctx, c.IP()).Result() resp.XRateRemaining, _ = strconv.Atoi(val) - ttl, _ := r2.TTL(database.Ctx, c.IP()).Result() - resp.XRateLimitReset = ttl/time.Nanosecond / time.Minute + ttl, _ := r2.TTL(helpers.Ctx, c.IP()).Result() + resp.XRateLimitReset = ttl / time.Nanosecond / time.Minute resp.CustomShort = os.Getenv("DOMAIN_RETURN") + "/" + id - + return c.Status(fiber.StatusCreated).JSON(resp) -} \ No newline at end of file +} diff --git a/api/routes/statistical.go b/api/routes/statistical.go index 8ce2eaa..1b08b50 100644 --- a/api/routes/statistical.go +++ b/api/routes/statistical.go @@ -3,8 +3,10 @@ package routes import ( "fmt" "os" + "github.com/gofiber/fiber/v2" - "github.com/thuongtruong1009/short1url/database" + "github.com/thuongtruong109/onelink/database" + "github.com/thuongtruong109/onelink/helpers" ) func AllShortedURLsOfUser(c *fiber.Ctx) error { @@ -13,25 +15,35 @@ func AllShortedURLsOfUser(c *fiber.Ctx) error { r := database.CreateClient(0) defer r.Close() - result, err := r.SMembers(database.Ctx, "index:" + ip).Result() + result, err := r.SMembers(helpers.Ctx, helpers.INDEX+ip).Result() if err != nil { - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "cannot retrieve client"}) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": helpers.CANNOT_RETRIEVE_CLIENT}) } var updatedResult []string - // Iterate over the set members for _, member := range result { - value, err := r.Get(database.Ctx, member).Result() + value, err := r.Get(helpers.Ctx, member).Result() if err != nil { - return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "cannot retrieve URLs of client"}) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": helpers.CANNOT_RETRIEVE_URLS_OF_CLIENT}) } - updatedResult = append(updatedResult, os.Getenv("DOMAIN") + "/" + member) + updatedResult = append(updatedResult, os.Getenv("DOMAIN")+"/"+member) fmt.Printf("Key: %s, Value: %s\n", member, value) } return c.Status(fiber.StatusOK).JSON(updatedResult) } - \ No newline at end of file + +func AllShortedURLs(c *fiber.Ctx) error { + r := database.CreateClient(0) + defer r.Close() + + result, err := r.Keys(helpers.Ctx, "*").Result() + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": helpers.CANNOT_RETRIEVE_ALL_URLS}) + } + + return c.Status(fiber.StatusOK).JSON(fiber.Map{"count": len(result)}) +}