DEV Community

Cover image for How to build a URL Shortener with Go
Ekemini Samuel
Ekemini Samuel

Posted on • Edited on

How to build a URL Shortener with Go

Say you've created a Google doc or saw a link to a video and want to share it with your friend, but the link needs to be shorter. That's where URL shorteners help. Some even go a step further and allow you to customise the link.

I often shorten and customise my links using bitly.

In my previous article, I shared that I'll focus on two things - Go for backend development and Technical writing. This is to show I'm committed. What better way to learn than to apply and teach?

We'll be building a simple URL shortener with Go 😃, my fave programming language.

Shall we?... Yes!

Prerequisites

  • Go installed on your system, download here
  • A code editor - try VS Code
  • The willingness to be a gopher 😁

Design

The URL shortener will be a basic web application that handles HTTP requests, shortens URLs, and redirects users to the original URLs using unique shortened keys. We will us an in-memory map to store the relationships between the shortened keys and original URLs.

The Build Flow

Let's start by writing the code for our URL shortener. We'll break down the implementation into the following steps:

Step 1: Set up the Project

Open your termial and create a new directory for the project, then initialize a Go module to manage dependencies.



mkdir go-url-short

cd go-url-short

go mod init go-url-short


Enter fullscreen mode Exit fullscreen mode

go mod init is to create a new go.mod file, which will be a module in the project folder.

snip of go.mod file in VS code

You can open up the folder from VS Code, or while in your terminal, enter code .

Step 2: Import the Packages

Go is all about packages - they're the core of every Go program.
Create a filed named main.go in the project directory, and enter the code below:



package main

import (
    "fmt"
    "math/rand"
    "net/http"
    "time"
)


Enter fullscreen mode Exit fullscreen mode

In this initial step, we import the necessary packages for our Go program. We're using fmt for formatting and printing, math/rand for generating random keys, net/http for handling HTTP requests, and time for seeding the random number generator.

Step 3: Define the URL Shortener Struct



type URLShortener struct {
    urls map{string}string
}


Enter fullscreen mode Exit fullscreen mode

We create a URLShortener struct to manage the mapping between original URLs and their shortened versions. This struct will have a urls field, which is a map with shortened keys as keys and original URLs as values.

Step 4: Implement URL Shortening



func (us *URLShortener) HandleShorten(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
        return
    }

    originalURL := r.FormValue("url")
    if originalURL == "" {
        http.Error(w, "URL parameter is missing", http.StatusBadRequest)
        return
    }

    // Generate a unique shortened key for the original URL
    shortKey := generateShortKey()
    us.urls[shortKey] = originalURL

    // Construct the full shortened URL
    shortenedURL := fmt.Sprintf("http://localhost:8080/short/%s", shortKey)

    // Render the HTML response with the shortened URL
    w.Header().Set("Content-Type", "text/html")
    responseHTML := fmt.Sprintf(`
        <h2>URL Shortener</h2>
        <p>Original URL: %s</p>
        <p>Shortened URL: <a href="%s">%s</a></p>
        <form method="post" action="/shorten">
            <input type="text" name="url" placeholder="Enter a URL">
            <input type="submit" value="Shorten">
        </form>
    `, originalURL, shortenedURL, shortenedURL)
    fmt.Fprintf(w, responseHTML)
}



Enter fullscreen mode Exit fullscreen mode

Here, we define a HandleShorten method for the URLShortener struct. This method handles POST requests, validates the input URL, generates a unique short key, and displays the original and shortened URLs in an HTML response along with an input form for users to enter more URLs.

Step 5: Implement URL Redirection



func (us *URLShortener) HandleRedirect(w http.ResponseWriter, r *http.Request) {
    shortKey := r.URL.Path[len("/short/"):]
    if shortKey == "" {
        http.Error(w, "Shortened key is missing", http.StatusBadRequest)
        return
    }

    // Retrieve the original URL from the `urls` map using the shortened key
    originalURL, found := us.urls[shortKey]
    if !found {
        http.Error(w, "Shortened key not found", http.StatusNotFound)
        return
    }

    // Redirect the user to the original URL
    http.Redirect(w, r, originalURL, http.StatusMovedPermanently)
}



Enter fullscreen mode Exit fullscreen mode

Step 6: Generate Short Keys



func generateShortKey() string {
    const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    const keyLength = 6

    rand.Seed(time.Now().UnixNano())
    shortKey := make([]byte, keyLength)
    for i := range shortKey {
        shortKey[i] = charset[rand.Intn(len(charset))]
    }
    return string(shortKey)
}


Enter fullscreen mode Exit fullscreen mode

We create a generateShortKey function to generate unique short keys for the original URLs. This function generates a random alphanumeric key of length 6 characters, ensuring the uniqueness of the keys.

Step 7: Main Function and Server Setup



func main() {
    shortener := &URLShortener{
        urls: make(map[string]string),
    }

    http.HandleFunc("/shorten", shortener.HandleShorten)
    http.HandleFunc("/short/", shortener.HandleRedirect)

    fmt.Println("URL Shortener is running on :8080")
    http.ListenAndServe(":8080", nil)
}



Enter fullscreen mode Exit fullscreen mode

In the main function, we create an instance of the URLShortener struct and set up the HTTP handlers for URL shortening and redirection. We listen on port 8081, and the server starts running.

Running the URL Shortener

To run the URL shortener, follow these steps:

  • Save the provided Go code in a file named main.go.
  • Open a terminal or use the one in your code editor, an navigate to the directory where the main.go file is located.
  • Run this go build command: ```go

go build -o go-url-short main.go

The `-o` flag is used to specify the output binary's name, which is named `go-url-short`.


![server is running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ucrg8j87qfj8ysibe915.png)

- Open a web browser and go to the URL:
```go


http://localhost:8081



Enter fullscreen mode Exit fullscreen mode
  • You should see the URL shortener web page with an input form. Enter a long URL, click "Shorten," and the page will display the original and shortened URLs.

Here's a GIF that shows the app running

GIF showing the app

The full code can be accessed on this GitHub repo.

Conclusion

Building a URL shortener with Go is a great way to learn about web development, HTTP handling, and working with data structures. Our simple implementation includes the essentials: URL shortening, redirection, and a basic HTML form for user interaction.

This project can be a starting point for enhancing the user interface, adding analytics, and exploring more advanced features.

Happy coding! 💻

Thanks for reading; you can support me by buying me a coffee/book :)

Top comments (12)

Collapse
 
eztosin profile image
Eztosin

This was a nice read, I never knew there was a way to shorten urls... Thank you!

Collapse
 
envitab profile image
Ekemini Samuel

Thank you @eztosin. I'm glad it's helpful.

Collapse
 
jd2r profile image
DR

Really fun project! Thanks for writing such an in-depth article :)

Collapse
 
envitab profile image
Ekemini Samuel

Thank you @jd2r

I'm glad it was fun! 😎

Collapse
 
chideracode profile image
Chidera Humphrey

Nice read.

Thanks for sharing.

Collapse
 
envitab profile image
Ekemini Samuel

Thank you Chidera

Collapse
 
onyebuenyi_prince profile image
Onyebuenyi Prince

Thanks for sharing

Collapse
 
envitab profile image
Ekemini Samuel

You're welcome! Thank you for reading :)

Collapse
 
gabsii profile image
Lukas Gabsi

Hey, this was a nice article to get my own url shortener started :)
However, I think there is one small problem rebuilding the project will lead to the existing shortUrls being lost! Maybe this should be included in the post somewhere

Collapse
 
envitab profile image
Ekemini Samuel

Hey Lukas!

Great! Glad you tried out the tutorial!

Could you share more about the issue you had with the existing URLs?

Collapse
 
rajjmalla10 profile image
rajjmalla10

Thankyou sir

Collapse
 
envitab profile image
Ekemini Samuel

You're welcome