Go_URL_Shortner

Go Distributed & Scalable Link Shortener API

📌 Demo & Code

Live Demo View on GitHub

1. Problem Statement

In today’s digital world, long and complicated URLs can be difficult to use, share, and manage. To solve this, there’s a need for a fast, secure, and scalable service that can turn these long URLs into short, memorable, and trackable links. At the same time, the service must protect against misuse and ensure that important data remains available as needed. This project was built to meet those needs by providing a clean, reliable API for creating and managing short URLs — along with useful features like expiration, validation, and rate limiting.

2. Technology Stack & Rationale

3. High-Level Design (HLD)

The Link Shortener API is architected as a stateless microservice, designed for horizontal scalability.

+------------------+     HTTPS     +---------------------+     HTTP/S     +-------------------+
|   Client Device  | <------------>|   Render (Proxy)    | <------------->|   Go API Service  |
| (Browser/cURL)   |               | (HTTPS Termination) |                | (Docker Container)|
+------------------+               +---------------------+                +--------+----------+
                                                                                   |
                                                                                   | TLS
                                                                                   |
                                                                           +-------+--------+
                                                                           | Upstash Redis  |
                                                                           | (Data Storage, |
                                                                           | Rate Limiting) |
                                                                           +----------------+

Workflow:

  1. Request Ingress: Client applications initiate HTTP/HTTPS requests directed towards the public API endpoint.

  2. Render Proxy (HTTPS Termination): In deployment scenarios leveraging Render, the platform’s infrastructure intercepts the incoming HTTPS request. It subsequently manages the TLS termination process and forwards a standard HTTP request to the internal Go API service.

  3. Go API Service:

    • Rate Limiting: Upon receipt of a URL shortening request, the service initially consults the Redis-based rate limiter to ascertain whether the client (identified by its IP address) remains within the predefined request limits. Should these limits be exceeded, an HTTP 429 Method Not Allowed response is issued.

    • URL Validation: Inbound long URLs undergo stringent validation to confirm their adherence to the https scheme and to detect the presence of any malicious script injection attempts.

    • Duplicate Verification: Prior to the generation of a new short URL, the service queries Redis to determine if the specified long_url has been previously shortened. If an existing entry is found, the corresponding short_url is returned, and its Time-To-Live (TTL) is extended.

    • short Generation/Assignment: In instances where a custom short is not provided, a unique 6-character alphanumeric short is algorithmically generated. Conversely, if a custom short is furnished, its uniqueness is rigorously verified.

    • Redis Persistence: The mapping between (short_url -> long_url) and (long_url -> short_url) is persistently stored within Redis, each with a 7-day TTL.

    • Response Generation: A JSON response, encapsulating the short_url, the original long_url, and the limit_remaining for rate limiting purposes, is then transmitted to the client.

  4. Redirection: For a GET request targeting a short URL, the service retrieves the corresponding long_url from Redis and issues an HTTP 301 (Moved Permanently) redirect directive to the client.

  5. Redis Connectivity: The Go application establishes and maintains a secure TLS-encrypted connection to the Upstash Redis instance for all data storage and retrieval operations.

4. Features

5. API Usage

Upon successful deployment and initiation, the application’s functionality is accessible via its defined HTTP/HTTPS endpoints.

Base URLs

5.1. Shorten a URL

This endpoint facilitates the conversion of an extended URL into a more concise form, with the option to specify a custom short.

5.2. Redirect from Short URL

This endpoint performs a redirection operation from a shortened URL to its original, extended counterpart.

5.3. Health Check

A diagnostic endpoint provided to ascertain the operational status of the service.

6. Local Setup

The following procedures outline the steps required to establish and operate the application within a local development environment utilizing Docker Compose.

Prerequisites

Steps

  1. Repository Cloning:

    git clone <your-repository-url>
    cd <your-project-directory>
    
  2. .env File Creation: A file named .env must be created in the root directory of your project and subsequently populated with the necessary configuration parameters. Note: It is imperative to replace your_redis_password with the actual password associated with your Redis instance. For Upstash, this detail is critically important.

    REDIS_ADDR=your_redis_addr:6379 # localhost:6379
    REDIS_PASSWORD=your_redis_password
    REDIS_DB=0
    HTTP_PORT=8080
    HTTPS_PORT=8443 # Applicable solely for local HTTPS testing
    TLS_CERT_PATH=/app/localhost.crt # Applicable solely for local HTTPS testing
    TLS_KEY_PATH=/app/localhost.key  # Applicable solely for local HTTPS testing
    
  3. Self-Signed SSL Certificate Generation (for Local HTTPS Testing): These certificates are indispensable for accessing the application via https://localhost:8443. Execute the following command within your project’s root directory:

    openssl req -x509 -newkey rsa:4096 -nodes -keyout localhost.key -out localhost.crt -days 365 -subj "/CN=localhost"
    

    This operation will yield localhost.crt and localhost.key files, which will be placed in your project’s root directory.

  4. Go Module Initialization: This step is crucial for ensuring that all project dependencies are downloaded and that go.mod and go.sum files are correctly configured.

    go mod init link-shortener # If not previously initialized, substitute 'link-shortener' with your module's designated name.
    go mod tidy
    
  5. Docker Compose Build and Execution: This command initiates the construction of your Go application’s Docker image and subsequently launches the containers.

    docker-compose up --build
    

    Should an Could not connect to Redis: EOF error be encountered, it is advisable to verify the accuracy of REDIS_PASSWORD in your .env file and confirm that TLSConfig is appropriately passed to both Redis client initializations within main.go and redis/redis.go.

7. Deployment on Render

This application is engineered for straightforward deployment on Render, or comparable platforms that offer integrated Docker support and automatic HTTPS management.

  1. Code Preparation:

    • It is essential to ensure that main.go is configured to listen on the PORT environment variable (which Render dynamically supplies). The local HTTPS setup, involving localhost.crt and localhost.key, is not required for Render deployments.

    • Confirm that your Dockerfile does not include instructions to copy localhost.crt and localhost.key into the image.

    • All modifications to your codebase must be committed to a Git repository (e.g., GitHub, GitLab, Bitbucket).

  2. Render Web Service Configuration:

    • Navigate to https://render.com/ and proceed to create a new Web Service.

    • Establish a connection to your Git repository.

    • Name: Assign a unique identifier to your service.

    • Runtime: Select Docker (Render typically performs automatic detection).

    • Build Command: This field should remain empty.

    • Start Command: This field should remain empty.

    • Plan Type: Choose the desired service plan.

    • Environment Variables: It is critical to add the following environment variables within Render’s dashboard interface:

      • REDIS_ADDR: Your actual Upstash Redis address

      • REDIS_PASSWORD: Your actual Upstash Redis password.

      • REDIS_DB: 0

      • PORT: 8080 (This denotes the internal port on which your Go application listens).

    • Initiate the service creation by clicking “Create Web Service”.

  3. Automatic HTTPS Implementation: Render will automatically provision and administer an SSL/TLS certificate for your service, thereby providing a secure https:// Uniform Resource Locator (e.g., https://your-service-name.onrender.com). Explicit HTTPS configuration within your Go application code is thus rendered unnecessary for Render deployments.

8. Important Notes

9. Scope for Future Development


📌 Demo & Code

Live Demo View on GitHub

```