How to build a URL Shortener with Go
Ekemini Samuel
Posted on August 11, 2023
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
go mod init
is to create a new go.mod
file, which will be a module in the project folder.
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"
)
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
}
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)
}
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)
}
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)
}
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)
}
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
- 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
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 :)
Posted on August 11, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.