-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add a tutorial example for URL Shortner built using DiceDB and Go #1259
base: master
Are you sure you want to change the base?
feat: Add a tutorial example for URL Shortner built using DiceDB and Go #1259
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for contributing a tutorial for dicedb. It's a great way to help new users get started.
I have left some comments on this PR, please address them.
Hi @JyotinderSingh, I have addressed above mentioned review changes and pushed the code. Please take a look at it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor comments in the shortener code.
examples/url-shotener/main.go
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: typo in directory name url-shortner
examples/url-shotener/main.go
Outdated
// Initialize DiceDB connection | ||
func init() { | ||
db = dicedb.NewClient(&dicedb.Options{ | ||
Addr: "localhost:7379", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get hostname and port from ENV variables?
Similar to:
dice/examples/leaderboard-go/main.go
Lines 36 to 44 in 44779c2
dhost := "localhost" | |
if val := os.Getenv("DICEDB_HOST"); val != "" { | |
dhost = val | |
} | |
dport := "7379" | |
if val := os.Getenv("DICEDB_PORT"); val != "" { | |
dport = val | |
} |
examples/url-shotener/main.go
Outdated
} | ||
|
||
// Creates a short URL from a given long URL | ||
func CreateShortURL(c *gin.Context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
func CreateShortURL(c *gin.Context) { | |
func createShortURL(c *gin.Context) { |
examples/url-shotener/main.go
Outdated
} | ||
|
||
// Redirects to the original URL based on the short URL ID | ||
func RedirectURL(c *gin.Context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
func RedirectURL(c *gin.Context) { | |
func redirectURL(c *gin.Context) { |
examples/url-shotener/main.go
Outdated
requestBody.ID = shortID | ||
requestBody.ShortURL = "http://localhost:8080/" + shortID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to store ID
and ShortURL
in the struct?
Having just LongURL
is sufficient?
The mapping b/w ID
and LongURL
is anyway stored in the DiceDB.
Thanks for addressing the comments @Prachi-Jamdade. Could you please resolve comments by @everlearner as well? |
Hey @JyotinderSingh, pushed the code addressing changes raised by @everlearner |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for making the changes.
Hey @JyotinderSingh, any update ? |
Will review soon |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing the reviews so far @Prachi-Jamdade. Documentation is a critical aspect of any project, and needs to be extremely polished. Keeping that in mind I've suggested some improvements.
1. Go installed (at least version 1.18) | ||
2. DiceDB server running locally |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. Go installed (at least version 1.18) | |
2. DiceDB server running locally | |
1. Go (version 1.18 or later): [Download Go](https://golang.org/dl/) | |
2. DiceDB: A DiceDB server running locally. Refer to the [DiceDB Installation Guide](https://github.com/DiceDB/dice/pull/1259/get-started/installation) if you haven't set it up yet. |
## 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
## 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. | |
## Understanding DiceDB Commands | |
We'll use the following DiceDB commands: | |
### `SET` Command | |
Stores a key-value pair in DiceDB. | |
- **Syntax**: `SET key value [expiration]` | |
- `key`: Unique identifier (e.g., short URL code) | |
- `value`: Data to store (e.g., serialized JSON) | |
- `expiration`: Optional; time-to-live in seconds (use `0` for no expiration) | |
### `GET` Command | |
Retrieves the value associated with a key. | |
- **Syntax**: `GET key` | |
- `key`: Identifier for the data to retrieve |
Syntax - `Get(key)` | ||
`key`: The identifier for the data to retrieve. | ||
|
||
## Code overview |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
## Code overview | |
## Writing the Code | |
Create a file named `main.go` and add the following code: |
} | ||
``` | ||
|
||
## Explanation of Key Parts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
## Explanation of Key Parts | |
## Explanation |
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`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should make use of subheadings to make this clearer. PTAL at the following approach to write this:
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`. | |
### 1. Initialize the DiceDB Client | |
We set up the DiceDB client in the `init` function: | |
```go | |
db = dicedb.NewClient(&dicedb.Options{ | |
Addr: "localhost:7379", | |
}) | |
``` | |
### 2. Create Short URL Endpoint | |
- **Input Validation**: Ensures the `long_url` field is present. | |
- **Short ID Generation**: Uses `uuid` to create a unique 8-character ID. | |
- **Data Serialization**: Converts the `URL` struct to JSON. | |
- **Data Storage**: Saves the JSON data in DiceDB with the `Set` command. | |
- **Response**: Returns the generated short URL. | |
### 3. Redirect to Original URL Endpoint | |
- **Data Retrieval**: Fetches the URL data from DiceDB using the `Get` command. | |
- **Data Deserialization**: Converts JSON back to the `URL` struct. | |
- **Redirection**: Redirects the user to the `LongURL`. | |
### 4. Start the Server | |
The `main` function sets up the routes and starts the server on port `8080`. |
## Interacting with the application | ||
|
||
1. Start DiceDB: Ensure DiceDB is running. | ||
2. Test the API: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2. Test the API: | |
## Testing the Application | |
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 | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 | |
``` | |
**Using `curl`:** | |
```bash | |
curl -X POST -H "Content-Type: application/json" -d '{"long_url": "https://example.com"}' http://localhost:8080/shorten | |
``` | |
**Response:** | |
```json | |
{ | |
"short_url": "http://localhost:8080/<short ID generated by the server>" | |
} | |
``` |
Send a GET request to `/:id` with the short URL ID on Postman | ||
|
||
OR | ||
|
||
```curl | ||
curl -L http://localhost:8080/{short_id} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Send a GET request to `/:id` with the short URL ID on Postman | |
OR | |
```curl | |
curl -L http://localhost:8080/{short_id} | |
``` | |
**Using `curl`:** | |
```bash | |
curl -L http://localhost:8080/abcd1234 | |
``` | |
**Using a Browser:** | |
Navigate to: | |
``` | |
http://localhost:8080/abcd1234 | |
``` | |
You should be redirected to `https://example.com`. |
examples/url-shortener/.dockerignore
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is not needed.
examples/url-shortener/Dockerfile
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need such a detailed dockerfile, the following is fine:
# Build Stage
FROM golang:1.23 AS builder
WORKDIR /app
# Copy go.mod and go.sum to download dependencies
COPY go.mod go.sum ./
RUN go mod download
# Copy application source code and build
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server .
# Runtime Stage
FROM alpine:latest
# Install runtime dependencies
RUN apk --no-cache add ca-certificates
# Copy the built application
WORKDIR /root/
COPY --from=builder /app/server .
# Expose the application port
EXPOSE 8080
# Start the application
CMD ["./server"]
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 | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 | |
``` | |
### 1. Install and Run DiceDB | |
Start a DiceDB server using Docker: | |
```bash | |
docker run -d -p 7379:7379 dicedb/dicedb | |
``` | |
This command pulls the DiceDB Docker image and runs it, exposing it on port `7379`. | |
### 2. Initialize a New Go Project | |
Create a new directory for your project and initialize a Go module: | |
```bash | |
mkdir url-shortener | |
cd url-shortener | |
go mod init url-shortener | |
``` | |
### 3. Install Required Packages | |
Install the DiceDB Go SDK and other dependencies: | |
```bash | |
go get github.com/dicedb/dicedb-go | |
go get github.com/gin-gonic/gin | |
go get github.com/google/uuid | |
``` |
@Prachi-Jamdade hope you are doing well, are you actively working on this PR? |
Hey @JyotinderSingh, yes I'll push changes by tomorrow morning. Got stuck in end sem exams. I'll address them quickly. |
Thanks for the update! No rush. |
Hey @JyotinderSingh, addressed your changes. |
This commit adds an example of how to integrate the DiceDB Go SDK for building a URL shortener application.
The tutorial walks through setting up a basic URL shortening service, providing -
The application utilizes the
Set
andGet
commands from DiceDB to store and retrieve shortened URLs, and the example is designed to help developers quickly understand and implement a URL shortener using DiceDB and Go.