URL Shortener
๐ Overviewโ
Middleware Path: internal/api/v1/url-shortener/redirector.js
The URL Shortener provides short URL creation and redirection with visit tracking. Core responsibilities include:
- URL Redirection: Redirect short codes to target URLs
- Visit Tracking: Increment visit counter on each redirect
- URL Validation: Ensure proper URL format with protocol
- 404 Handling: Handle invalid or expired short codes
๐๏ธ Collections Usedโ
- short-urls (link removed - file does not exist) - Short URL mappings
code(String) - Unique short codeurl(String) - Target URLvisit(Number) - Visit counteraccount_id(ObjectId) - Owner accountcreated_by(ObjectId) - Creator user
๐ Data Flowโ
URL Redirection Flowโ
sequenceDiagram
participant User
participant Middleware
participant ShortURL
participant Database
participant TargetSite
User->>Middleware: GET /:code
Note over User,Middleware: Example: GET /abc123
Middleware->>Database: Find short URL by code
Database-->>Middleware: Short URL document
alt Code Not Found
Middleware-->>User: 404 Not Found
else Code Found
Middleware->>Database: Increment visit counter
Database-->>Middleware: Updated
Middleware->>Middleware: Validate URL format
Note over Middleware: Add https:// if missing
Middleware->>TargetSite: Redirect 302
TargetSite-->>User: Target page
end
style Middleware fill:#e3f2fd
style Database fill:#fff4e6
Visit Trackingโ
flowchart TD
A[Incoming Request] --> B[Extract code from URL]
B --> C{Code exists?}
C -->|No| D[Return 404 Not Found]
C -->|Yes| E[Increment visit counter]
E --> F{URL has protocol?}
F -->|Yes| G[Use URL as-is]
F -->|No| H[Add https:// prefix]
G --> I[302 Redirect to target]
H --> I
D --> J[End]
I --> J
style E fill:#e8f5e9
style I fill:#e3f2fd
๐ง Business Logic & Functionsโ
redirector(req, res)โ
Purpose: Middleware function to redirect short URLs to target URLs with visit tracking
Parameters:
req(Object) - Express request objectreq.params.code(String) - Short URL code from route parameter
res(Object) - Express response object
Returns: HTTP redirect (302) or 404 error
Business Logic Flow:
-
Find Short URL by Code
const ShortURL = require('../models/short-url');
const shortUrl = await ShortURL.findOne({
code: req.params.code,
});
if (!shortUrl) {
return res.status(404).send('Short URL not found');
} -
Increment Visit Counter
await ShortURL.updateOne({ _id: shortUrl._id }, { $inc: { visit: 1 } }); -
Validate and Normalize URL
let targetUrl = shortUrl.url;
// Add protocol if missing
if (!targetUrl.startsWith('http://') && !targetUrl.startsWith('https://')) {
targetUrl = 'https://' + targetUrl;
} -
Redirect to Target URL
return res.redirect(302, targetUrl);
Route Integration:
// Route definition in routes file
router.get('/:code', redirector);
Request Example:
GET /abc123 HTTP/1.1
Host: short.dashclicks.com
Response Example:
HTTP/1.1 302 Found
Location: https://example.com/long-url-path
Key Business Rules:
- Visit Tracking: Counter incremented atomically before redirect
- Protocol Normalization: HTTPS added if protocol missing
- 404 on Missing: Returns 404 if code doesn't exist
- No Authentication: Public endpoint, no auth required
- No Expiration: Short URLs don't expire automatically
๐ Integration Pointsโ
Link Creation Moduleโ
Create Short URL:
const ShortURL = require('../models/short-url');
const shortid = require('shortid');
// Create short URL
const shortUrl = await ShortURL.create({
code: shortid.generate(), // Generate unique code
url: 'https://example.com/long-url',
account_id: accountId,
created_by: userId,
visit: 0,
});
// Return short link
const shortLink = `https://short.dashclicks.com/${shortUrl.code}`;
Analytics Moduleโ
Track Click Analytics:
// Get visit statistics
const shortUrl = await ShortURL.findOne({ code: 'abc123' });
console.log(`Total visits: ${shortUrl.visit}`);
Email/SMS Campaignsโ
Use Short URLs in Messages:
// Replace long URLs with short URLs in email
const emailBody = `
Click here: https://short.dashclicks.com/${shortUrl.code}
`;
// Track clicks from campaign
const campaignClicks = await ShortURL.aggregate([
{
$match: {
campaign_id: campaignId,
},
},
{
$group: {
_id: null,
total_clicks: { $sum: '$visit' },
},
},
]);
๐งช Edge Cases & Special Handlingโ
Missing Protocol in Target URLโ
Auto-Add HTTPS:
let targetUrl = shortUrl.url;
if (!targetUrl.startsWith('http://') && !targetUrl.startsWith('https://')) {
targetUrl = 'https://' + targetUrl;
}
// Before: example.com
// After: https://example.com
Invalid Short Codeโ
404 Response:
const shortUrl = await ShortURL.findOne({ code: req.params.code });
if (!shortUrl) {
return res.status(404).send('Short URL not found');
}
Race Condition on Visit Counterโ
Atomic Increment:
// Use $inc operator for atomic counter increment
await ShortURL.updateOne({ _id: shortUrl._id }, { $inc: { visit: 1 } });
// This prevents race conditions when multiple users
// click the same short URL simultaneously
Malformed Target URLsโ
Potential Issue:
// Edge case: Invalid URL after normalization
targetUrl = 'javascript:alert("XSS")';
// Current implementation doesn't validate URL scheme
// Consider adding validation:
if (!targetUrl.startsWith('http://') && !targetUrl.startsWith('https://')) {
return res.status(400).send('Invalid target URL');
}
โ ๏ธ Important Notesโ
-
No Authentication: Redirect endpoint is public and doesn't require authentication. Anyone with the code can access the link.
-
Visit Counter: Incremented on every request, including bots, crawlers, and duplicate visits from same user.
-
302 Redirect: Uses temporary redirect (302) instead of permanent (301), allowing URL changes if needed.
-
Protocol Assumption: Defaults to HTTPS when protocol missing. HTTP URLs must explicitly include
http://. -
No Expiration: Short URLs don't have built-in expiration. Consider adding
expires_atfield for time-limited links. -
No Click Analytics: Only tracks visit count, not detailed analytics (timestamp, referrer, user agent, location).
-
No Rate Limiting: No rate limiting on redirects. Consider adding to prevent abuse.
-
Code Generation: Short codes generated elsewhere (typically using
shortidor similar library). -
Case Sensitive: Short codes are case-sensitive (
ABC123โabc123). -
No Preview: Direct redirect without preview page. Consider adding preview mode for security.
-
Error Handling: Minimal error handling. Database errors may cause 500 responses.
-
Performance: Single database query per redirect. Consider caching popular short URLs.
๐ Enhancement Opportunitiesโ
Advanced Analyticsโ
// Track detailed click data
await ShortURL.updateOne(
{ _id: shortUrl._id },
{
$inc: { visit: 1 },
$push: {
clicks: {
timestamp: new Date(),
ip: req.ip,
userAgent: req.headers['user-agent'],
referrer: req.headers['referer'],
},
},
},
);
Link Expirationโ
// Check expiration before redirect
if (shortUrl.expires_at && shortUrl.expires_at < new Date()) {
return res.status(410).send('This link has expired');
}
Custom Domainsโ
// Support multiple short domains
const domain = req.hostname;
const shortUrl = await ShortURL.findOne({
code: req.params.code,
domain: domain,
});
Preview Modeโ
// Show preview page instead of direct redirect
if (req.query.preview === 'true') {
return res.render('preview', {
targetUrl: shortUrl.url,
code: shortUrl.code,
});
}
๐ Related Documentationโ
- Link Management (link removed - file does not exist) - Short URL creation and management
- Analytics Module (link removed - file does not exist) - Click tracking and reporting
- Campaigns (link removed - file does not exist) - Short URL usage in campaigns
- Security Practices (link removed - file does not exist) - URL validation and XSS prevention