From 87976a44cc37e4bf632405bd09bc0735fb821412 Mon Sep 17 00:00:00 2001 From: Prachi-Jamdade Date: Sat, 9 Nov 2024 19:26:34 +0530 Subject: [PATCH 1/6] feat: Add a tutorial example for URL Shortner built using DiceDB and Go --- .../content/docs/get-started/url-shortner.mdx | 306 ++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 docs/src/content/docs/get-started/url-shortner.mdx diff --git a/docs/src/content/docs/get-started/url-shortner.mdx b/docs/src/content/docs/get-started/url-shortner.mdx new file mode 100644 index 000000000..67d7515ac --- /dev/null +++ b/docs/src/content/docs/get-started/url-shortner.mdx @@ -0,0 +1,306 @@ +--- +title: "Building a URL Shortner" +description: "Create a simple URL Shortner using DiceDB Go SDK." +sidebar: + order: 5 +--- + +This tutorial guides you through creating a URL shortener using DiceDB, a key-value store, with Go. We’ll set up endpoints to generate short URLs and redirect them to the original URLs. + +Prerequisites + +1. Go installed (at least version 1.18) +2. DiceDB server running locally +3. Basic familiarity with Go and DiceDB + +## Environment setup + +Refer to [DiceDB Installation Guide](https://dicedb.io/get-started/installation/) to get your DiceDB server up and running with a simple Docker command. + +## Starting the application server + +1. Clone the repository + ```bash + git clone https://github.com/Prachi-Jamdade/url-shortner-go-dicedb + cd url-shortner-go-dicedb + ``` +2. Start the application + ```bash + go run main.go + ``` + This will start the application server on port 8080 by default, you should see output similar to + ```bash + [GIN-debug] Listening and serving HTTP on :8080 + ``` + +## Interacting with the application + +1. *Start DiceDB*: Ensure DiceDB is running. +2. *Test the API*: + - Shorten URL: + Send a POST request to `/shorten` with JSON body on Postman: + ``` + { + "long_url": "https://example.com" + } + ``` + + OR + + ```curl + curl -X POST -H "Content-Type: application/json" + -d '{"long_url": "https://example.com"}' http://localhost:8080/shorten + ``` + + - Redirect to Original URL: + Send a GET request to `/:id` with the short URL ID on Postman + + OR + + ```curl + curl -L http://localhost:8080/{short_id} + ``` + +## DiceDB Commands Used + +Here are the main DiceDB commands we’ll use to store and retrieve URLs. + +1. `Set` Command: Stores a key-value pair in DiceDB. +Syntax - `Set(key, value, expiration)` +`key`: Unique identifier (e.g., short URL code) +`value`: The data to store (serialized JSON) +`expiration`: Optional; 0 means no expiration + +2. `Get` Command: Retrieves the value associated with a key. +Syntax - `Get(key)` +`key`: The identifier for the data to retrieve. + +## Project Structure + +The project is organized into several packages: + +- `models`: Defines the URL data structure. +- `repository`: Handles database interactions with DiceDB. +- `services`: Implements business logic for URL shortening. +- `handlers`: Contains HTTP route handlers for the API. +- `utils`: Provides helper functions for API responses. + +## Code overview + +1. `models/url.go`: Defines the URL struct, which represents the data to be stored in DiceDB. + + ```go + package models + + type URL struct { + ID string `json:"id"` + LongURL string `json:"long_url"` + ShortURL string `json:"short_url"` + } + ``` + + - This struct will be serialized to JSON before saving in DiceDB. + +2. `repository/url_repository.go`: Handles interactions with DiceDB, using `Set` and `Get` commands to store and retrieve URL data. + + ```go + package repository + + import ( + "context" + "encoding/json" + "errors" + "fmt" + "url-shortner-dicedb/models" + + "github.com/dicedb/dicedb-go" // DiceDB Go SDK + ) + + var db *dicedb.Client + + func init() { + db = dicedb.NewClient(&dicedb.Options{ + Addr: "localhost:7379", + }) + } + + // SaveURL stores a URL in DiceDB + func SaveURL(url models.URL) error { + ctx := context.Background() + + // Serialize the URL struct to JSON + urlData, err := json.Marshal(url) + if err != nil { + return fmt.Errorf("failed to serialize URL: %w", err) + } + + // Store the serialized URL JSON in DiceDB + statusCmd := db.Set(ctx, url.ID, urlData, 0) + _, err = statusCmd.Result() + if err != nil { + return fmt.Errorf("failed to save URL: %w", err) + } + return nil + } + + // FindURLByID retrieves a URL by its ID + func FindURLByID(id string) (models.URL, error) { + ctx := context.Background() + + // Retrieve the serialized URL data from DiceDB + stringCmd := db.Get(ctx, id) + urlData, err := stringCmd.Result() + if err != nil { + if err == dicedb.Nil { + return models.URL{}, errors.New("URL not found") + } + return models.URL{}, fmt.Errorf("failed to retrieve URL: %w", err) + } + + // Deserialize the JSON data back into the URL struct + var url models.URL + err = json.Unmarshal([]byte(urlData), &url) + if err != nil { + return models.URL{}, fmt.Errorf("failed to decode URL data: %w", err) + } + return url, nil + } + ``` + + - `Marshaling` (converting struct to JSON) and `unmarshaling` (converting JSON to struct) are necessary because DiceDB stores data as strings, and we need structured data to access individual fields easily. + +3. `services/url_service.go`: Implements business logic for creating and retrieving URLs. + + ```go + package services + + import ( + "fmt" + "url-shortner-dicedb/models" + "url-shortner-dicedb/repository" + + "github.com/google/uuid" + ) + + func CreateShortURLService(longURL string) (string, error) { + id := uuid.New().String()[:8] // Shorten ID for URL + + url := models.URL{ + ID: id, + LongURL: longURL, + ShortURL: "http://localhost:8080/" + id, + } + + if err := repository.SaveURL(url); err != nil { + fmt.Println(err) + return "", err + } + + return url.ShortURL, nil + } + + func GetOriginalURLService(id string) (string, error) { + url, err := repository.FindURLByID(id) + if err != nil { + return "", err + } + + return url.LongURL, nil + } + + ``` + + - The `CreateShortURLService` function generates a unique ID for each URL and stores it using `SaveURL`. + +4. `handlers/url_handler.go`: Defines HTTP endpoints for creating and redirecting URLs. + + ```go + package handlers + + import ( + "net/http" + "url-shortner-dicedb/models" + "url-shortner-dicedb/services" + "url-shortner-dicedb/utils" + + "github.com/gin-gonic/gin" + ) + + func RegisterRoutes(router *gin.Engine) { + router.POST("/shorten", CreateShortURL) + router.GET("/:id", RedirectURL) + } + + func CreateShortURL(c *gin.Context) { + var requestBody models.URL + if err := c.ShouldBindJSON(&requestBody); err != nil { + utils.RespondWithError(c, http.StatusBadRequest, "Invalid request") + return + } + + shortURL, err := services.CreateShortURLService(requestBody.LongURL) + if err != nil { + utils.RespondWithError(c, http.StatusInternalServerError, "Error creating short URL") + return + } + + utils.RespondWithJSON(c, http.StatusCreated, gin.H{"short_url": shortURL}) + } + + func RedirectURL(c *gin.Context) { + id := c.Param("id") + longURL, err := services.GetOriginalURLService(id) + if err != nil { + utils.RespondWithError(c, http.StatusNotFound, "URL not found") + return + } + + c.Redirect(http.StatusFound, longURL) + } + ``` + + - `CreateShortURL` handles POST requests to generate a short URL. + - `RedirectURL` redirects to the original URL based on the short ID. + +5. `utils/response.go`: Provides helper functions for consistent JSON responses. + + ```go + package utils + + import ( + "github.com/gin-gonic/gin" + ) + + func RespondWithError(c *gin.Context, code int, message string) { + c.JSON(code, gin.H{"error": message}) + } + + func RespondWithJSON(c *gin.Context, code int, payload interface{}) { + c.JSON(code, payload) + } + ``` + +6. `main.go`: Sets up the Gin (a HTTP Web Framework) router and registers routes. This is the entry point of the application. + + ```go + package main + + import ( + "log" + "url-shortner-dicedb/handlers" + "github.com/gin-gonic/gin" + ) + + func main() { + router := gin.Default() + handlers.RegisterRoutes(router) + log.Fatal(router.Run(":8080")) + } + ``` + +## Conclusion + +This project demonstrates how to set up a simple yet functional API for URL shortening, which can be expanded further with additional features or integrated into a larger application. With Go’s performance and DiceDB’s efficiency, this offers a lightweight solution for URL management. + +Find the complete code for this example on [Github](https://github.com/Prachi-Jamdade/url-shortner-go-dicedb). + From c1a2b474aa065d862567303e56efcff3b9be7a84 Mon Sep 17 00:00:00 2001 From: Prachi-Jamdade Date: Sat, 9 Nov 2024 23:13:53 +0530 Subject: [PATCH 2/6] fix: Address review changes --- .../content/docs/get-started/url-shortner.mdx | 306 ------------------ .../content/docs/tutorials/url-shortner.md | 186 +++++++++++ 2 files changed, 186 insertions(+), 306 deletions(-) delete mode 100644 docs/src/content/docs/get-started/url-shortner.mdx create mode 100644 docs/src/content/docs/tutorials/url-shortner.md diff --git a/docs/src/content/docs/get-started/url-shortner.mdx b/docs/src/content/docs/get-started/url-shortner.mdx deleted file mode 100644 index 67d7515ac..000000000 --- a/docs/src/content/docs/get-started/url-shortner.mdx +++ /dev/null @@ -1,306 +0,0 @@ ---- -title: "Building a URL Shortner" -description: "Create a simple URL Shortner using DiceDB Go SDK." -sidebar: - order: 5 ---- - -This tutorial guides you through creating a URL shortener using DiceDB, a key-value store, with Go. We’ll set up endpoints to generate short URLs and redirect them to the original URLs. - -Prerequisites - -1. Go installed (at least version 1.18) -2. DiceDB server running locally -3. Basic familiarity with Go and DiceDB - -## Environment setup - -Refer to [DiceDB Installation Guide](https://dicedb.io/get-started/installation/) to get your DiceDB server up and running with a simple Docker command. - -## Starting the application server - -1. Clone the repository - ```bash - git clone https://github.com/Prachi-Jamdade/url-shortner-go-dicedb - cd url-shortner-go-dicedb - ``` -2. Start the application - ```bash - go run main.go - ``` - This will start the application server on port 8080 by default, you should see output similar to - ```bash - [GIN-debug] Listening and serving HTTP on :8080 - ``` - -## Interacting with the application - -1. *Start DiceDB*: Ensure DiceDB is running. -2. *Test the API*: - - Shorten URL: - Send a POST request to `/shorten` with JSON body on Postman: - ``` - { - "long_url": "https://example.com" - } - ``` - - OR - - ```curl - curl -X POST -H "Content-Type: application/json" - -d '{"long_url": "https://example.com"}' http://localhost:8080/shorten - ``` - - - Redirect to Original URL: - Send a GET request to `/:id` with the short URL ID on Postman - - OR - - ```curl - curl -L http://localhost:8080/{short_id} - ``` - -## DiceDB Commands Used - -Here are the main DiceDB commands we’ll use to store and retrieve URLs. - -1. `Set` Command: Stores a key-value pair in DiceDB. -Syntax - `Set(key, value, expiration)` -`key`: Unique identifier (e.g., short URL code) -`value`: The data to store (serialized JSON) -`expiration`: Optional; 0 means no expiration - -2. `Get` Command: Retrieves the value associated with a key. -Syntax - `Get(key)` -`key`: The identifier for the data to retrieve. - -## Project Structure - -The project is organized into several packages: - -- `models`: Defines the URL data structure. -- `repository`: Handles database interactions with DiceDB. -- `services`: Implements business logic for URL shortening. -- `handlers`: Contains HTTP route handlers for the API. -- `utils`: Provides helper functions for API responses. - -## Code overview - -1. `models/url.go`: Defines the URL struct, which represents the data to be stored in DiceDB. - - ```go - package models - - type URL struct { - ID string `json:"id"` - LongURL string `json:"long_url"` - ShortURL string `json:"short_url"` - } - ``` - - - This struct will be serialized to JSON before saving in DiceDB. - -2. `repository/url_repository.go`: Handles interactions with DiceDB, using `Set` and `Get` commands to store and retrieve URL data. - - ```go - package repository - - import ( - "context" - "encoding/json" - "errors" - "fmt" - "url-shortner-dicedb/models" - - "github.com/dicedb/dicedb-go" // DiceDB Go SDK - ) - - var db *dicedb.Client - - func init() { - db = dicedb.NewClient(&dicedb.Options{ - Addr: "localhost:7379", - }) - } - - // SaveURL stores a URL in DiceDB - func SaveURL(url models.URL) error { - ctx := context.Background() - - // Serialize the URL struct to JSON - urlData, err := json.Marshal(url) - if err != nil { - return fmt.Errorf("failed to serialize URL: %w", err) - } - - // Store the serialized URL JSON in DiceDB - statusCmd := db.Set(ctx, url.ID, urlData, 0) - _, err = statusCmd.Result() - if err != nil { - return fmt.Errorf("failed to save URL: %w", err) - } - return nil - } - - // FindURLByID retrieves a URL by its ID - func FindURLByID(id string) (models.URL, error) { - ctx := context.Background() - - // Retrieve the serialized URL data from DiceDB - stringCmd := db.Get(ctx, id) - urlData, err := stringCmd.Result() - if err != nil { - if err == dicedb.Nil { - return models.URL{}, errors.New("URL not found") - } - return models.URL{}, fmt.Errorf("failed to retrieve URL: %w", err) - } - - // Deserialize the JSON data back into the URL struct - var url models.URL - err = json.Unmarshal([]byte(urlData), &url) - if err != nil { - return models.URL{}, fmt.Errorf("failed to decode URL data: %w", err) - } - return url, nil - } - ``` - - - `Marshaling` (converting struct to JSON) and `unmarshaling` (converting JSON to struct) are necessary because DiceDB stores data as strings, and we need structured data to access individual fields easily. - -3. `services/url_service.go`: Implements business logic for creating and retrieving URLs. - - ```go - package services - - import ( - "fmt" - "url-shortner-dicedb/models" - "url-shortner-dicedb/repository" - - "github.com/google/uuid" - ) - - func CreateShortURLService(longURL string) (string, error) { - id := uuid.New().String()[:8] // Shorten ID for URL - - url := models.URL{ - ID: id, - LongURL: longURL, - ShortURL: "http://localhost:8080/" + id, - } - - if err := repository.SaveURL(url); err != nil { - fmt.Println(err) - return "", err - } - - return url.ShortURL, nil - } - - func GetOriginalURLService(id string) (string, error) { - url, err := repository.FindURLByID(id) - if err != nil { - return "", err - } - - return url.LongURL, nil - } - - ``` - - - The `CreateShortURLService` function generates a unique ID for each URL and stores it using `SaveURL`. - -4. `handlers/url_handler.go`: Defines HTTP endpoints for creating and redirecting URLs. - - ```go - package handlers - - import ( - "net/http" - "url-shortner-dicedb/models" - "url-shortner-dicedb/services" - "url-shortner-dicedb/utils" - - "github.com/gin-gonic/gin" - ) - - func RegisterRoutes(router *gin.Engine) { - router.POST("/shorten", CreateShortURL) - router.GET("/:id", RedirectURL) - } - - func CreateShortURL(c *gin.Context) { - var requestBody models.URL - if err := c.ShouldBindJSON(&requestBody); err != nil { - utils.RespondWithError(c, http.StatusBadRequest, "Invalid request") - return - } - - shortURL, err := services.CreateShortURLService(requestBody.LongURL) - if err != nil { - utils.RespondWithError(c, http.StatusInternalServerError, "Error creating short URL") - return - } - - utils.RespondWithJSON(c, http.StatusCreated, gin.H{"short_url": shortURL}) - } - - func RedirectURL(c *gin.Context) { - id := c.Param("id") - longURL, err := services.GetOriginalURLService(id) - if err != nil { - utils.RespondWithError(c, http.StatusNotFound, "URL not found") - return - } - - c.Redirect(http.StatusFound, longURL) - } - ``` - - - `CreateShortURL` handles POST requests to generate a short URL. - - `RedirectURL` redirects to the original URL based on the short ID. - -5. `utils/response.go`: Provides helper functions for consistent JSON responses. - - ```go - package utils - - import ( - "github.com/gin-gonic/gin" - ) - - func RespondWithError(c *gin.Context, code int, message string) { - c.JSON(code, gin.H{"error": message}) - } - - func RespondWithJSON(c *gin.Context, code int, payload interface{}) { - c.JSON(code, payload) - } - ``` - -6. `main.go`: Sets up the Gin (a HTTP Web Framework) router and registers routes. This is the entry point of the application. - - ```go - package main - - import ( - "log" - "url-shortner-dicedb/handlers" - "github.com/gin-gonic/gin" - ) - - func main() { - router := gin.Default() - handlers.RegisterRoutes(router) - log.Fatal(router.Run(":8080")) - } - ``` - -## Conclusion - -This project demonstrates how to set up a simple yet functional API for URL shortening, which can be expanded further with additional features or integrated into a larger application. With Go’s performance and DiceDB’s efficiency, this offers a lightweight solution for URL management. - -Find the complete code for this example on [Github](https://github.com/Prachi-Jamdade/url-shortner-go-dicedb). - diff --git a/docs/src/content/docs/tutorials/url-shortner.md b/docs/src/content/docs/tutorials/url-shortner.md new file mode 100644 index 000000000..bcd7b65b0 --- /dev/null +++ b/docs/src/content/docs/tutorials/url-shortner.md @@ -0,0 +1,186 @@ +--- +title: "Building a URL Shortner" +description: "Create a simple URL Shortner using DiceDB Go SDK." +--- + +This tutorial guides you through creating a URL shortener using DiceDB, a key-value store, with Go. We’ll set up endpoints to generate short URLs and redirect them to the original URLs. + +Prerequisites + +1. Go installed (at least version 1.18) +2. DiceDB server running locally + +## Setup + +1. Refer to [DiceDB Installation Guide](get-started/installation) to get your DiceDB server up and running with a simple Docker command. +2. Initialize a New Go Project +3. Install DiceDB Go SDK and other required packges. + ```bash + go get github.com/dicedb/dicedb-go + go get github.com/gin-gonic/gin + go get github.com/google/uuid + ``` + +## DiceDB Commands Used + +Here are the main DiceDB commands we’ll use to store and retrieve URLs. + +1. `Set` Command: Stores a key-value pair in DiceDB. +Syntax - `Set(key, value, expiration)` +`key`: Unique identifier (e.g., short URL code) +`value`: The data to store (serialized JSON) +`expiration`: Optional; 0 means no expiration + +2. `Get` Command: Retrieves the value associated with a key. +Syntax - `Get(key)` +`key`: The identifier for the data to retrieve. + +## Project Structure + +The project is organized into several packages: + +- `models`: Defines the URL data structure. +- `repository`: Handles database interactions with DiceDB. +- `services`: Implements business logic for URL shortening. +- `handlers`: Contains HTTP route handlers for the API. +- `utils`: Provides helper functions for API responses. + +## Code overview + +- `main.go`: + ```go + package main + + import ( + "context" + "encoding/json" + "log" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/dicedb/dicedb-go" // DiceDB Go SDK + ) + + type URL struct { + ID string `json:"id"` + LongURL string `json:"long_url"` + ShortURL string `json:"short_url"` + } + + var db *dicedb.Client + + // Initialize DiceDB connection + func init() { + db = dicedb.NewClient(&dicedb.Options{ + Addr: "localhost:7379", + }) + } + + // Creates a short URL from a given long URL + func CreateShortURL(c *gin.Context) { + var requestBody URL + if err := c.ShouldBindJSON(&requestBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + return + } + + // Generate unique short ID and construct the short URL + shortID := uuid.New().String()[:8] + requestBody.ID = shortID + requestBody.ShortURL = "http://localhost:8080/" + shortID + + // Serialize URL struct to JSON and store it in DiceDB + urlData, err := json.Marshal(requestBody) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + if err := db.Set(context.Background(), shortID, urlData, 0).Err(); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + c.JSON(http.StatusCreated, gin.H{"short_url": requestBody.ShortURL}) + } + + // Redirects to the original URL based on the short URL ID + func RedirectURL(c *gin.Context) { + id := c.Param("id") + + // Retrieve stored URL data from DiceDB + urlData, err := db.Get(context.Background(), id).Result() + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "URL not found"}) + return + } + + // Deserialize JSON data back into URL struct + var url URL + if err := json.Unmarshal([]byte(urlData), &url); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to decode URL data"}) + return + } + + // Redirect user to the original long URL + c.Redirect(http.StatusFound, url.LongURL) + } + + func main() { + router := gin.Default() + + // Define endpoints for creating short URLs and redirecting + router.POST("/shorten", CreateShortURL) + router.GET("/:id", RedirectURL) + + // Start the server on port 8080 + if err := router.Run(":8080"); err != nil { + log.Fatal("Failed to start server:", err) + } + } + ``` + +## Explanation of Key Parts +1. Database Initialization: The `init()` function sets up a DiceDB client to connect to `localhost:7379`. +2. `CreateShortURL` Endpoint: Handles the `/shorten` route. It generates a unique ID, constructs the short URL, serializes the URL data, and saves it in DiceDB. +3. `RedirectURL` Endpoint: Handles the `/:id` route. It retrieves the original URL by the short ID from DiceDB and redirects the user to it. +4. Starting the Server: The `main` function starts the Gin server on port `8080`. + +## Starting the application server + +1. Start the application + ```bash + go run main.go + ``` + This will start the application server on port 8080 by default, you should see output similar to + ```bash + [GIN-debug] Listening and serving HTTP on :8080 + ``` + +## Interacting with the application + +1. Start DiceDB: Ensure DiceDB is running. +2. Test the API: + - Shorten URL: + Send a POST request to `/shorten` with JSON body on Postman: + ``` + { + "long_url": "https://example.com" + } + ``` + + OR + + ```curl + curl -X POST -H "Content-Type: application/json" -d '{"long_url": "https://example.com"}' http://localhost:8080/shorten + ``` + + - Redirect to Original URL: + Send a GET request to `/:id` with the short URL ID on Postman + + OR + + ```curl + curl -L http://localhost:8080/{short_id} + ``` From 30d29a38231220e7e10235d6c0becdb3e3c7a880 Mon Sep 17 00:00:00 2001 From: Prachi-Jamdade Date: Sat, 9 Nov 2024 23:16:43 +0530 Subject: [PATCH 3/6] chore: Add tutotial code to examples --- examples/url-shotener/.dockerignore | 32 ++++++++++ examples/url-shotener/Dockerfile | 78 +++++++++++++++++++++++++ examples/url-shotener/compose.yaml | 17 ++++++ examples/url-shotener/go.mod | 41 +++++++++++++ examples/url-shotener/go.sum | 87 +++++++++++++++++++++++++++ examples/url-shotener/main.go | 91 +++++++++++++++++++++++++++++ 6 files changed, 346 insertions(+) create mode 100644 examples/url-shotener/.dockerignore create mode 100644 examples/url-shotener/Dockerfile create mode 100644 examples/url-shotener/compose.yaml create mode 100644 examples/url-shotener/go.mod create mode 100644 examples/url-shotener/go.sum create mode 100644 examples/url-shotener/main.go diff --git a/examples/url-shotener/.dockerignore b/examples/url-shotener/.dockerignore new file mode 100644 index 000000000..9e03c4843 --- /dev/null +++ b/examples/url-shotener/.dockerignore @@ -0,0 +1,32 @@ +# Include any files or directories that you don't want to be copied to your +# container here (e.g., local build artifacts, temporary files, etc.). +# +# For more help, visit the .dockerignore file reference guide at +# https://docs.docker.com/go/build-context-dockerignore/ + +**/.DS_Store +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/bin +**/charts +**/docker-compose* +**/compose.y*ml +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md diff --git a/examples/url-shotener/Dockerfile b/examples/url-shotener/Dockerfile new file mode 100644 index 000000000..8716022fa --- /dev/null +++ b/examples/url-shotener/Dockerfile @@ -0,0 +1,78 @@ +# syntax=docker/dockerfile:1 + +# Comments are provided throughout this file to help you get started. +# If you need more help, visit the Dockerfile reference guide at +# https://docs.docker.com/go/dockerfile-reference/ + +# Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7 + +################################################################################ +# Create a stage for building the application. +ARG GO_VERSION=1.23.2 +FROM --platform=$BUILDPLATFORM golang:${GO_VERSION} AS build +WORKDIR /src + +# Download dependencies as a separate step to take advantage of Docker's caching. +# Leverage a cache mount to /go/pkg/mod/ to speed up subsequent builds. +# Leverage bind mounts to go.sum and go.mod to avoid having to copy them into +# the container. +RUN --mount=type=cache,target=/go/pkg/mod/ \ + --mount=type=bind,source=go.sum,target=go.sum \ + --mount=type=bind,source=go.mod,target=go.mod \ + go mod download -x + +# This is the architecture you're building for, which is passed in by the builder. +# Placing it here allows the previous steps to be cached across architectures. +ARG TARGETARCH + +# Build the application. +# Leverage a cache mount to /go/pkg/mod/ to speed up subsequent builds. +# Leverage a bind mount to the current directory to avoid having to copy the +# source code into the container. +RUN --mount=type=cache,target=/go/pkg/mod/ \ + --mount=type=bind,target=. \ + CGO_ENABLED=0 GOARCH=$TARGETARCH go build -o /bin/server . + +################################################################################ +# Create a new stage for running the application that contains the minimal +# runtime dependencies for the application. This often uses a different base +# image from the build stage where the necessary files are copied from the build +# stage. +# +# The example below uses the alpine image as the foundation for running the app. +# By specifying the "latest" tag, it will also use whatever happens to be the +# most recent version of that image when you build your Dockerfile. If +# reproducability is important, consider using a versioned tag +# (e.g., alpine:3.17.2) or SHA (e.g., alpine@sha256:c41ab5c992deb4fe7e5da09f67a8804a46bd0592bfdf0b1847dde0e0889d2bff). +FROM alpine:latest AS final + +# Install any runtime dependencies that are needed to run your application. +# Leverage a cache mount to /var/cache/apk/ to speed up subsequent builds. +RUN --mount=type=cache,target=/var/cache/apk \ + apk --update add \ + ca-certificates \ + tzdata \ + && \ + update-ca-certificates + +# Create a non-privileged user that the app will run under. +# See https://docs.docker.com/go/dockerfile-user-best-practices/ +ARG UID=10001 +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "/nonexistent" \ + --shell "/sbin/nologin" \ + --no-create-home \ + --uid "${UID}" \ + appuser +USER appuser + +# Copy the executable from the "build" stage. +COPY --from=build /bin/server /bin/ + +# Expose the port that the application listens on. +EXPOSE 8080 + +# What the container should run when it is started. +ENTRYPOINT [ "/bin/server" ] diff --git a/examples/url-shotener/compose.yaml b/examples/url-shotener/compose.yaml new file mode 100644 index 000000000..fad46cb2b --- /dev/null +++ b/examples/url-shotener/compose.yaml @@ -0,0 +1,17 @@ +services: + dicedb: + image: dicedb/dicedb:latest + ports: + - "7379:7379" + + url-shortener: + build: + context: . + dockerfile: Dockerfile + ports: + - "8000:8000" + depends_on: + - dicedb + environment: + - DICEDB_HOST=dicedb + - DICEDB_PORT=7379 diff --git a/examples/url-shotener/go.mod b/examples/url-shotener/go.mod new file mode 100644 index 000000000..38d6216a5 --- /dev/null +++ b/examples/url-shotener/go.mod @@ -0,0 +1,41 @@ +module url-shotener + +go 1.23.2 + +require github.com/gin-gonic/gin v1.10.0 + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect +) + +require ( + github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/dicedb/dicedb-go v0.0.0-20241026093718-570de4575be3 + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.20.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/google/uuid v1.6.0 + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/examples/url-shotener/go.sum b/examples/url-shotener/go.sum new file mode 100644 index 000000000..289e93e92 --- /dev/null +++ b/examples/url-shotener/go.sum @@ -0,0 +1,87 @@ +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dicedb/dicedb-go v0.0.0-20241026093718-570de4575be3 h1:JvnAibMNGA0vQH+T47Y/d5/POURIvfJl3fFk0GIEBkQ= +github.com/dicedb/dicedb-go v0.0.0-20241026093718-570de4575be3/go.mod h1:p7x5/3S6wBEmiRMwxavj1I1P1xsSVQS6fcSbeai5ic4= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/examples/url-shotener/main.go b/examples/url-shotener/main.go new file mode 100644 index 000000000..86d0502a4 --- /dev/null +++ b/examples/url-shotener/main.go @@ -0,0 +1,91 @@ +package main + +import ( + "context" + "encoding/json" + + "log" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/dicedb/dicedb-go" // DiceDB Go SDK +) + +type URL struct { + ID string `json:"id"` + LongURL string `json:"long_url"` + ShortURL string `json:"short_url"` +} + +var db *dicedb.Client + +// Initialize DiceDB connection +func init() { + db = dicedb.NewClient(&dicedb.Options{ + Addr: "localhost:7379", + }) +} + +// Creates a short URL from a given long URL +func CreateShortURL(c *gin.Context) { + var requestBody URL + if err := c.ShouldBindJSON(&requestBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + return + } + + // Generate unique short ID and construct the short URL + shortID := uuid.New().String()[:8] + requestBody.ID = shortID + requestBody.ShortURL = "http://localhost:8080/" + shortID + + // Serialize URL struct to JSON and store it in DiceDB + urlData, err := json.Marshal(requestBody) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + if err := db.Set(context.Background(), shortID, urlData, 0).Err(); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + c.JSON(http.StatusCreated, gin.H{"short_url": requestBody.ShortURL}) +} + +// Redirects to the original URL based on the short URL ID +func RedirectURL(c *gin.Context) { + id := c.Param("id") + + // Retrieve stored URL data from DiceDB + urlData, err := db.Get(context.Background(), id).Result() + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "URL not found"}) + return + } + + // Deserialize JSON data back into URL struct + var url URL + if err := json.Unmarshal([]byte(urlData), &url); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to decode URL data"}) + return + } + + // Redirect user to the original long URL + c.Redirect(http.StatusFound, url.LongURL) +} + +func main() { + router := gin.Default() + + // Define endpoints for creating short URLs and redirecting + router.POST("/shorten", CreateShortURL) + router.GET("/:id", RedirectURL) + + // Start the server on port 8080 + if err := router.Run(":8080"); err != nil { + log.Fatal("Failed to start server:", err) + } +} From 7a48a75ca7a39af165a821d92084c09bde2e3c86 Mon Sep 17 00:00:00 2001 From: Prachi-Jamdade Date: Sat, 9 Nov 2024 23:23:59 +0530 Subject: [PATCH 4/6] fix: Remove project structure from tutorial doc --- docs/src/content/docs/tutorials/url-shortner.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/docs/src/content/docs/tutorials/url-shortner.md b/docs/src/content/docs/tutorials/url-shortner.md index bcd7b65b0..86e26ecc5 100644 --- a/docs/src/content/docs/tutorials/url-shortner.md +++ b/docs/src/content/docs/tutorials/url-shortner.md @@ -35,16 +35,6 @@ Syntax - `Set(key, value, expiration)` Syntax - `Get(key)` `key`: The identifier for the data to retrieve. -## Project Structure - -The project is organized into several packages: - -- `models`: Defines the URL data structure. -- `repository`: Handles database interactions with DiceDB. -- `services`: Implements business logic for URL shortening. -- `handlers`: Contains HTTP route handlers for the API. -- `utils`: Provides helper functions for API responses. - ## Code overview - `main.go`: From af08fe83d04f1dfb554e455451c39b678d61e87f Mon Sep 17 00:00:00 2001 From: Prachi-Jamdade Date: Thu, 14 Nov 2024 21:54:01 +0530 Subject: [PATCH 5/6] fix: Fix typo in directory name, tutorial doc --- .../docs/tutorials/{url-shortner.md => url-shortener.md} | 4 ++-- examples/{url-shotener => url-shortener}/.dockerignore | 0 examples/{url-shotener => url-shortener}/Dockerfile | 0 examples/{url-shotener => url-shortener}/compose.yaml | 0 examples/{url-shotener => url-shortener}/go.mod | 2 +- examples/{url-shotener => url-shortener}/go.sum | 0 examples/{url-shotener => url-shortener}/main.go | 0 7 files changed, 3 insertions(+), 3 deletions(-) rename docs/src/content/docs/tutorials/{url-shortner.md => url-shortener.md} (98%) rename examples/{url-shotener => url-shortener}/.dockerignore (100%) rename examples/{url-shotener => url-shortener}/Dockerfile (100%) rename examples/{url-shotener => url-shortener}/compose.yaml (100%) rename examples/{url-shotener => url-shortener}/go.mod (98%) rename examples/{url-shotener => url-shortener}/go.sum (100%) rename examples/{url-shotener => url-shortener}/main.go (100%) diff --git a/docs/src/content/docs/tutorials/url-shortner.md b/docs/src/content/docs/tutorials/url-shortener.md similarity index 98% rename from docs/src/content/docs/tutorials/url-shortner.md rename to docs/src/content/docs/tutorials/url-shortener.md index 86e26ecc5..61eada7f5 100644 --- a/docs/src/content/docs/tutorials/url-shortner.md +++ b/docs/src/content/docs/tutorials/url-shortener.md @@ -1,6 +1,6 @@ --- -title: "Building a URL Shortner" -description: "Create a simple URL Shortner using DiceDB Go SDK." +title: "Building a URL Shortener" +description: "Create a simple URL Shortener using DiceDB Go SDK." --- This tutorial guides you through creating a URL shortener using DiceDB, a key-value store, with Go. We’ll set up endpoints to generate short URLs and redirect them to the original URLs. diff --git a/examples/url-shotener/.dockerignore b/examples/url-shortener/.dockerignore similarity index 100% rename from examples/url-shotener/.dockerignore rename to examples/url-shortener/.dockerignore diff --git a/examples/url-shotener/Dockerfile b/examples/url-shortener/Dockerfile similarity index 100% rename from examples/url-shotener/Dockerfile rename to examples/url-shortener/Dockerfile diff --git a/examples/url-shotener/compose.yaml b/examples/url-shortener/compose.yaml similarity index 100% rename from examples/url-shotener/compose.yaml rename to examples/url-shortener/compose.yaml diff --git a/examples/url-shotener/go.mod b/examples/url-shortener/go.mod similarity index 98% rename from examples/url-shotener/go.mod rename to examples/url-shortener/go.mod index 38d6216a5..1dbd9137d 100644 --- a/examples/url-shotener/go.mod +++ b/examples/url-shortener/go.mod @@ -1,4 +1,4 @@ -module url-shotener +module url-shortener go 1.23.2 diff --git a/examples/url-shotener/go.sum b/examples/url-shortener/go.sum similarity index 100% rename from examples/url-shotener/go.sum rename to examples/url-shortener/go.sum diff --git a/examples/url-shotener/main.go b/examples/url-shortener/main.go similarity index 100% rename from examples/url-shotener/main.go rename to examples/url-shortener/main.go From 597ce6adf35e0f0e2e80e97a0e0429d211e3be6d Mon Sep 17 00:00:00 2001 From: Prachi-Jamdade Date: Thu, 14 Nov 2024 22:40:19 +0530 Subject: [PATCH 6/6] chore: remove unnecessary mapping of longurl and shorturl in code, make functions unexported --- examples/url-shortener/main.go | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/examples/url-shortener/main.go b/examples/url-shortener/main.go index 86d0502a4..583eb8a02 100644 --- a/examples/url-shortener/main.go +++ b/examples/url-shortener/main.go @@ -3,6 +3,8 @@ package main import ( "context" "encoding/json" + "os" + "fmt" "log" "net/http" @@ -13,22 +15,30 @@ import ( ) type URL struct { - ID string `json:"id"` LongURL string `json:"long_url"` - ShortURL string `json:"short_url"` } var db *dicedb.Client // Initialize DiceDB connection func init() { + dhost := "localhost" + if val := os.Getenv("DICEDB_HOST"); val != "" { + dhost = val + } + + dport := "7379" + if val := os.Getenv("DICEDB_PORT"); val != "" { + dport = val + } + db = dicedb.NewClient(&dicedb.Options{ - Addr: "localhost:7379", + Addr: fmt.Sprintf("%s:%s", dhost, dport), }) } // Creates a short URL from a given long URL -func CreateShortURL(c *gin.Context) { +func createShortURL(c *gin.Context) { var requestBody URL if err := c.ShouldBindJSON(&requestBody); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) @@ -37,8 +47,7 @@ func CreateShortURL(c *gin.Context) { // Generate unique short ID and construct the short URL shortID := uuid.New().String()[:8] - requestBody.ID = shortID - requestBody.ShortURL = "http://localhost:8080/" + shortID + shortURL := "http://localhost:8080/" + shortID // Serialize URL struct to JSON and store it in DiceDB urlData, err := json.Marshal(requestBody) @@ -52,11 +61,11 @@ func CreateShortURL(c *gin.Context) { return } - c.JSON(http.StatusCreated, gin.H{"short_url": requestBody.ShortURL}) + c.JSON(http.StatusCreated, gin.H{"short_url": shortURL}) } // Redirects to the original URL based on the short URL ID -func RedirectURL(c *gin.Context) { +func redirectURL(c *gin.Context) { id := c.Param("id") // Retrieve stored URL data from DiceDB @@ -81,8 +90,8 @@ func main() { router := gin.Default() // Define endpoints for creating short URLs and redirecting - router.POST("/shorten", CreateShortURL) - router.GET("/:id", RedirectURL) + router.POST("/shorten", createShortURL) + router.GET("/:id", redirectURL) // Start the server on port 8080 if err := router.Run(":8080"); err != nil {