🚀 A full-stack URL shortening service built with Spring Boot (Java) and deployed on AWS EC2 using Nginx as a reverse proxy and MySQL (RDS) for persistence. Convert long URLs into short, manageable aliases under the custom d50.in domain.
- 🔗 URL Shortening: Converts long, cumbersome URLs into neat short links.
- ✍️ Custom Aliases: Allows users to suggest a preferred short alias (e.g.,
d50.in/r/my-project). - 🎲 Random Aliases (Base62): Generates unique, 5-character Base62 (
[0-9a-zA-Z]) aliases automatically if no custom alias is provided. - ♻️ Duplicate URL Handling: If a long URL has already been shortened, the existing short link is returned, preventing duplicate entries.
- ➡️ Secure Redirection: Uses HTTP 301 Permanent Redirects for optimal SEO and performance when redirecting from the short link (
/r/{alias}) to the original URL. - 🖥️ Simple Frontend: A clean web interface built with HTML, CSS, and Vanilla JavaScript for easy submission of URLs.
- 🔒 HTTPS Enforced: All traffic is automatically redirected to HTTPS, secured using Nginx and free SSL certificates from Let's Encrypt.
- ☁️ Cloud Native: Designed and deployed on AWS infrastructure (EC2, RDS, Route 53).
(Note: H2 Database is used for local development/testing.)
The application follows a standard client-server architecture enhanced by a reverse proxy:
- User's Browser: Interacts with the static frontend (HTML/CSS/JS).
- Nginx (on EC2):
- Listens on ports 80 (HTTP) & 443 (HTTPS).
- Redirects all HTTP traffic to HTTPS.
- Terminates SSL for HTTPS traffic using Let's Encrypt certificates.
- Forwards valid HTTPS requests for
/api/*or/r/*to the Spring Boot application running internally on port 8080. - Adds crucial
X-Forwarded-*headers.
- Spring Boot Application (on EC2):
- Listens internally on
localhost:8080. - Handles API requests (
/api/shorten) and redirection logic (/r/{alias}). - Interacts with the database via Spring Data JPA.
- Configured to understand
X-Forwarded-*headers.
- Listens internally on
- AWS RDS (MySQL Database):
- Stores the
alias->long URLmappings persistently. - Accessible only from the EC2 instance via internal VPC networking (secured by Security Groups).
- Stores the
(Diagram Recommendation: Insert a clear architecture diagram image here showing the flow: User -> Browser -> Route 53 -> EC2 (Nginx -> Spring Boot) -> RDS)
| Method | Endpoint | Request Body / Path Params | Success Response | Error Response(s) | Description |
|---|---|---|---|---|---|
POST |
/api/shorten |
JSON (CreateRedirectRequest DTO) |
201 Created - JSON (RedirectResponse DTO) |
400 Bad Request (Validation, Alias Exists), 503 (Alias Gen) | Creates a new short URL or returns existing one. |
GET |
/r/{alias} |
Path Variable: alias (String) |
301 Moved Permanently (Location Header) |
404 Not Found | Redirects the user to the original long URL. |
DTOs:
CreateRedirectRequest:{ "url": "string (required)", "alias": "string (optional, max 10 chars, [a-zA-Z0-9-])" }RedirectResponse:{ "alias": "string", "originalUrl": "string", "shortUrl": "string (full https://d50.in/r/alias)" }
Table: redirects
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
id |
BIGINT |
Primary Key, Auto Increment | Unique record identifier. |
alias |
VARCHAR(10) |
Unique, Not Null | The short alias string. |
url |
VARCHAR(2048) |
Not Null | The original long URL. |
created_at |
TIMESTAMP |
Not Null, Defaults to Current Time | Timestamp of record creation. |
Read more about the development process, challenges faced, and deployment details in my blog post: