SpeedyShort is a lightweight, fast URL shortener written in Go. It uses an in-memory index for instant lookups and an embedded key-value store for persistence. No external services or databases are required.
- Random alphanumeric short codes
- Instant redirects (in-memory hash map)
- Persistent storage via Badger (embedded KV store)
- Clean and simple REST API
- Minimal static landing page
- No external dependencies
- Single self-contained binary
- Built-in rate limiting
- Domain blacklist with abuse reporting
- Telegram notifications for incoming reports
/
├─ main.go
├─ handlers.go
├─ storage.go
├─ background.go
├─ rate_limit.go
├─ config.go
├─ model.go
├─ blacklist.go
├─ telegram.go
├─ telegram.example.json
├─ public/
│ ├─ index.html
│ ├─ blocked.html
│ ├─ icon.svg
│ └─ favicon.ico
└─ cmd/
├─ listlinks/ – CLI tool to list all stored links
└─ adminctl/ – CLI tool for report review and domain management
All binaries are output to the bin/ directory.
go build -o bin/speedyshort .
go build -o bin/listlinks ./cmd/listlinks/
go build -o bin/adminctl ./cmd/adminctl/Cross-compile for Linux from another OS (e.g. macOS or Windows):
GOOS=linux GOARCH=amd64 go build -o bin/speedyshort .
GOOS=linux GOARCH=amd64 go build -o bin/listlinks ./cmd/listlinks/
GOOS=linux GOARCH=amd64 go build -o bin/adminctl ./cmd/adminctl/./bin/speedyshortDefault address:
http://localhost:8080
Environment variables:
FASTSHORTNER_BASE_URL – Base URL used inside generated short links
FASTSHORTNER_ADDR – Listen address (default: :8080)
FASTSHORTNER_DATA_DIR – Path to the Badger data directory (default: ./data)
FASTSHORTNER_TELEGRAM_CONFIG – Path to the Telegram config file (default: ./telegram.json)
Example:
FASTSHORTNER_BASE_URL="https://syrt.cc" FASTSHORTNER_ADDR=":8080" ./bin/speedyshortSpeedyShort can send a Telegram message when a new report is submitted, and lets you act on it by replying directly to the notification.
Copy the example config and fill in your values:
cp telegram.example.json telegram.json{
"bot_token": "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ",
"chat_ids": [123456789, 987654321]
}bot_token— token from @BotFatherchat_ids— list of Telegram user IDs that will receive notifications and are authorized to issue commands
If the file does not exist or is incomplete, the server starts normally with notifications disabled.
telegram.jsonis listed in.gitignoreand will never be committed.
When a report arrives you receive a notification like:
🚨 New report on SpeedyShort
Link: abc123
Reason: This link points to a phishing page
Reply with /b to ban the domain or /d to dismiss.
Reply to the message (not in a new message) with:
| Command | Action |
|---|---|
/b |
Resolve the domain from the reported input, blacklist it, deactivate all active links pointing to it, delete the report |
/d |
Delete the report without taking any action |
Domain resolution for /b:
The server resolves the domain to ban in this order:
- If the input is a short code or short URL → look up the target URL → extract its domain
- If the input is a full external URL → extract the domain directly
- If the input has no scheme (e.g.
evil.com/path) → prependhttps://and extract the domain
Note: the message↔report mapping is kept in memory. If the server restarts after a notification is sent, those old notifications can no longer be actioned via Telegram. Use
adminctlfor those cases.
POST /api/shorten
Headers
Content-Type: application/json
Body
{
"url": "https://www.example.com"
}Response
{
"code": "a7X9pQ",
"short_url": "http://localhost:8080/a7X9pQ",
"target_url": "https://www.example.com"
}Returns 403 Forbidden if the domain has been blacklisted.
GET /<code>
Returns 301 to the target URL, or a blocked page (451) if the link has been disabled.
POST /api/report
Body
{
"code": "a7X9pQ",
"reason": "This link points to a phishing page"
}The code field also accepts a full short URL (e.g. https://syrt.cc/a7X9pQ).
Constraints:
reason— required, between 10 and 100 characters- Rate limit: max 3 reports per IP per day
The report is recorded and queued for manual review. The link remains active until an administrator takes action. A Telegram notification is sent to all configured recipients.
Reports are reviewed and acted upon locally on the server using the adminctl tool.
Stop the server before running any write command.
systemctl stop speedyshort
# List all links pending review (shows code, report count, URL, reason)
./bin/adminctl reports /opt/speedyshort/data
# Deactivate a single reported link (domain is NOT blacklisted)
./bin/adminctl blacklist <code> /opt/speedyshort/data
# Blacklist a domain: all active links pointing to it are deactivated
./bin/adminctl blacklist-domain malicious.com /opt/speedyshort/data
# Dismiss a report without taking action (link stays active)
./bin/adminctl dismiss <code> /opt/speedyshort/data
# Show all blacklisted domains
./bin/adminctl blacklist-list /opt/speedyshort/data
systemctl start speedyshortIf FASTSHORTNER_DATA_DIR is set in the environment, the data-dir argument can be omitted.
The listlinks tool prints all links currently stored in the database.
Stop the server before running it.
systemctl stop speedyshort
./bin/listlinks /opt/speedyshort/data
systemctl start speedyshortStart the server and open:
http://localhost:8080
A minimal web interface is included for generating short links and submitting abuse reports.
You can try a live hosted version here:
This instance runs the exact same code from this repository.
SpeedyShort is released under the Prosperity Public License 3.0.0.
- Free for personal, research, and open-source use
- Commercial use requires a paid license
See the LICENSE file for the full text.