🚀 Demo : https://f-it.kr
A modern URL shortening service that features deep link handling and platform-specific redirections. The service uses email verification instead of account creation for a streamlined user experience while maintaining security.
Feature | Description |
---|---|
Efficient URL Generation | Quick short link creation using a collision-free algorithm |
Deep Link Handling | Platform detection and redirection for iOS/Android deep links |
Email Verification | Simple URL security through email verification without account creation |
Fallback Support | Configurable fallback URLs when apps aren't installed |
Webhook Integration | Track link usage with real-time access logs |
Our URL shortener implements an efficient system with several technical advantages.
The system uses specialized id_to_key
and key_to_id
functions as its foundation:
const CHARS: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
const BASE: i64 = 62;
/// ID To Key
/// Converts the primary key of the ShortURL table into a string.
/// Indexes when English lowercase/uppercase letters and numbers are sequentially combined.
pub fn id_to_key(mut id: i64) -> Option<String> {
if id < 1 {
return None;
}
let mut key = Vec::new();
while id > 0 {
id -= 1;
let digit = (id % BASE) as usize;
key.push(CHARS.as_bytes()[digit] as char);
id /= BASE;
}
key.reverse();
Some(key.iter().collect())
}
/// Key To ID
/// Converts arbitrary characters into a number.
/// Indexes when English lowercase/uppercase letters and numbers are sequentially combined.
pub fn key_to_id(key: &str) -> Option<i64> {
let mut result = 0i64;
for c in key.chars() {
let digit = CHARS.find(c)? as i64;
result = result * BASE + (digit + 1);
}
Some(result)
}
/// Split Short Key
/// Extracts the unique key in the middle and the random keys at the front and back.
pub fn split_short_key(short_key: &str) -> (String, String) {
let front_random_key = short_key[..2].to_string();
let back_random_key = short_key[short_key.len() - 2..].to_string();
let random_key = &(front_random_key + &back_random_key);
let unique_key = short_key[2..short_key.len() - 2].to_string();
(unique_key.to_string(), random_key.to_string())
}
- Creates a mapping between numbers and strings using alphanumeric characters (a-z, A-Z, 0-9)
- Ensures unique string representation for each number
- Examples:
- 1 → "a"
- 2 → "b"
- 27 → "A"
- 28 → "B"
- etc.
- Provides bidirectional mapping:
- IDs convert to unique strings
- Strings convert back to original IDs
- Conversion is deterministic and collision-free
-
Random Prefix/Suffix Generation
- Creates a 4-character random string
- Splits into two 2-character segments
-
Core Key Creation
- Stores URL data and receives unique ID
- Converts ID to string using
id_to_key
- Combines parts:
{2-char-prefix}{converted-id}{2-char-suffix}
-
Key Structure Example
If random key = "ABCD" and ID = 12345: - Prefix = "AB" - Converted ID = id_to_key(12345) - Suffix = "CD" Final key = "AB{converted-id}CD"
-
Uniqueness
- Each database ID creates a unique key
- No collision checking needed
- Random prefix/suffix adds security
-
Performance
- Consistent key generation time
- Stable performance as database grows
- No retry loops needed
-
Scalability
- Handles large URL volumes efficiently
- No practical limit on unique keys
- Suitable for high-traffic use
-
Implementation Benefits
- Memory efficient
- Minimal database queries
- Easy maintenance
- Clear debugging process
-
Security
- Unpredictable keys through random elements
- Protection against sequential guessing
- Balanced security and URL length
- Rust (backend)
- HTML (frontend)
Library | Version | Purpose |
---|---|---|
axum | 0.8.1 | Web framework |
tokio | 1.0 | Async runtime |
rusqlite | 0.32.1 | SQLite integration |
lettre | 0.11 | Email handling |
serde | 1.0 | JSON processing |
- Web interface for URL creation
- URL submission and customization UI
Creates short URLs through:
-
Input Validation
- URL format and accessibility checks
-
URL Processing
- Combines platform-specific URLs
- Generates unique hash
-
Email Verification (Optional when using JWT token)
- If JWT token is provided:
- Bypasses email verification
- Creates and returns the short URL immediately
- For existing URLs:
- Returns verification status
- Resends verification if pending
- For new URLs (without JWT token):
- Creates unverified URL
- Sends verification email
- Fetches og tags if not provided
- If JWT token is provided:
Handles verification:
-
Code Validation
- Checks code validity
- Verifies expiration status
-
Status Update
- Updates verification status
- Removes used code
- Confirms verification
Manages redirects:
-
Cache Check
- Queries Redis for URL data
-
Cache Hit Process
- Direct URL redirect
- Async webhook for analytics
- Platform-specific routing
-
Cache Miss Process
- Database retrieval
- Cache update
- User redirect
- Analytics webhook
-
Clone the repository:
git clone https://github.com/lee-lou2/rust-url-shortener
-
Configure environment variables:
SERVER_PROTOCOL=http SERVER_HOST=127.0.0.1 SERVER_PORT=3000 DATABASE_URL=sqlite://sqlite3.db EMAIL_ADDRESS= EMAIL_USER_NAME= EMAIL_PASSWORD= EMAIL_HOST= EMAIL_PORT= JWT_SECRET=
-
Set up email templates:
- Configure
templates/verify/error.html
- Configure
templates/verify/failed.html
- Update email address from default
your@email.com
- Configure
-
Initialize the database:
sh init_database.sh
5-1. Run the project:
cargo run
5-1. Run the project(Using Docker):
sh deploy.sh
- Platform-specific handling improvements
- Email template enhancements
- Admin dashboard
- Analytics features
- Test coverage expansion
- Docker support
We welcome contributions. To contribute:
- Fork the repository
- Create your feature branch
- Submit a pull request
This project is under the MIT License
For assistance:
- Review existing issues
- Open a new issue with details
- Participate in community discussions
Thank you for your interest in our URL Shortener Service.