Sign inSign up

e1saps/shortlinker

By e1saps

β€’Updated about 2 months ago

A lightning-fast URL shortener built with Rust, featuring HTTP 307 redirects and a clean, modern UI.

Buildkit cache
Image
Networking
Web servers
Content management system
1

4.3K

e1saps/shortlinker repository overview

⁠shortlinker

GitHub release (latest by date) Rust Release Docker Build CodeFactor License: MIT Docker Pulls

A minimalist URL shortener service supporting HTTP 307 redirection, built with Rust. Easy to deploy and lightning fast.

English⁠ β€’ 中文⁠

1749756794700

β πŸš€ Benchmark (v0.2.0)

Environment

  • OS: Linux
  • CPU: Single-core @ 12th Gen Intel(R) Core(TM) i5-12500
  • Tool: wrk⁠
TypeScenarioQPS PeakCache HitBloom FilterDB Access
Cache HitHot shortlink (repeated access)677,963.46βœ… Yesβœ… Yes❌ No
Cache MissCold shortlink (random access)600,622.46❌ Noβœ… Yesβœ… Yes

πŸ’‘ Even under cache miss, the system sustains nearly 600k QPS β€” demonstrating excellent performance with SQLite, actix-web, and async caching.

⁠✨ Features

  • πŸš€ High Performance: Built with Rust + Actix-web
  • 🎯 Dynamic Management: Add or remove links at runtime without restarting
  • 🎲 Smart Short Codes: Supports both custom and randomly generated codes
  • ⏰ Expiration Support: Set expiration times with flexible time formats (v0.1.1+)
  • πŸ’Ύ Multiple Storage Backends: SQLite database, JSON file storage
  • πŸ”„ Cross-Platform: Works on Windows, Linux, and macOS
  • πŸ›‘οΈ Admin API: HTTP API for link management (v0.0.5+)
  • πŸ₯ Health Monitoring: Built-in health check endpoints
  • 🐳 Containerized: Optimized Docker image for easy deployment
  • 🎨 Beautiful CLI: Colorized command-line interface
  • πŸ”Œ Unix Socket: Support for Unix socket binding

⁠Quick Start

⁠Run Locally
git clone https://github.com/AptS-1547/shortlinker
cd shortlinker
cargo run
⁠Deploy with Docker
# TCP port
docker run -d -p 8080:8080 -v $(pwd)/data:/data e1saps/shortlinker

# Unix socket
docker run -d -v $(pwd)/data:/data -v $(pwd)/sock:/sock \
  -e UNIX_SOCKET=/sock/shortlinker.sock e1saps/shortlinker

⁠Usage Example

Once your domain (e.g. esap.cc) is bound:

  • https://esap.cc/github β†’ custom short link
  • https://esap.cc/aB3dF1 β†’ random short link
  • https://esap.cc/ β†’ default homepage

⁠Command-Line Management

# Start the server
./shortlinker

# Add short links
./shortlinker add github https://github.com           # Custom code
./shortlinker add https://github.com                  # Random code
./shortlinker add github https://new-url.com --force  # Overwrite existing

# Using relative time format (v0.1.1+)
./shortlinker add daily https://example.com --expire 1d      # Expires in 1 day
./shortlinker add weekly https://example.com --expire 1w     # Expires in 1 week
./shortlinker add complex https://example.com --expire 1d2h30m  # Complex format

# Manage links
./shortlinker update github https://new-github.com --expire 30d
./shortlinker list                    # List all links
./shortlinker remove github           # Remove specific link

# Server control
./shortlinker start                   # Start server
./shortlinker stop                    # Stop server
./shortlinker restart                 # Restart server

⁠Admin API (v0.0.5+)

HTTP API for link management with Bearer token authentication.

⁠Setup
export ADMIN_TOKEN=your_secret_token
export ADMIN_ROUTE_PREFIX=/admin  # optional
⁠Examples
# Get all links
curl -H "Authorization: Bearer your_secret_token" \
     http://localhost:8080/admin/link

# Create link with relative time
curl -X POST \
     -H "Authorization: Bearer your_secret_token" \
     -H "Content-Type: application/json" \
     -d '{"code":"github","target":"https://github.com","expires_at":"7d"}' \
     http://localhost:8080/admin/link

# Auto-generate random code
curl -X POST \
     -H "Authorization: Bearer your_secret_token" \
     -H "Content-Type: application/json" \
     -d '{"target":"https://github.com","expires_at":"30d"}' \
     http://localhost:8080/admin/link

# Update link
curl -X PUT \
     -H "Authorization: Bearer your_secret_token" \
     -H "Content-Type: application/json" \
     -d '{"target":"https://new-url.com"}' \
     http://localhost:8080/admin/link/github

# Delete link
curl -X DELETE \
     -H "Authorization: Bearer your_secret_token" \
     http://localhost:8080/admin/link/github

⁠Health Check API

Monitor service health and storage status.

# Setup
export HEALTH_TOKEN=your_health_token

# Health check
curl -H "Authorization: Bearer your_health_token" \
     http://localhost:8080/health

# Readiness check
curl http://localhost:8080/health/ready

# Liveness check  
curl http://localhost:8080/health/live

⁠Time Format Support (v0.1.1+)

1s, 5m, 2h, 1d, 1w, 1M, 1y    # Single units
1d2h30m                        # Combined format
⁠RFC3339 Format
2024-12-31T23:59:59Z           # UTC time
2024-12-31T23:59:59+08:00      # With timezone

⁠Configuration

shortlinker now supports TOML configuration files!

Supports both TOML configuration files and environment variables. TOML configuration is clearer and more readable, so it's recommended.

⁠Custom Configuration File Path

You can specify a custom configuration file path using the -c or --config parameter:

# Use custom config file
./shortlinker -c /path/to/your/config.toml
./shortlinker --config /path/to/your/config.toml

# If the specified file doesn't exist, it will be created automatically with default settings
./shortlinker -c /etc/shortlinker/custom.toml
# [INFO] Configuration file not found: /etc/shortlinker/custom.toml
# [INFO] Creating default configuration file...
# [INFO] Default configuration file created at: /etc/shortlinker/custom.toml
⁠TOML Configuration File

Create a config.toml file:

[server]
# Server listening address
host = "127.0.0.1"
# Server listening port
port = 8080
# Unix Socket path (if set, overrides host and port)
# unix_socket = "/tmp/shortlinker.sock"
# CPU core count (defaults to system cores)
cpu_count = 4

[storage]
# Storage backend type: sqlite, postgres, mysql, mariadb
# πŸ’‘ This field is now OPTIONAL - the database type can be automatically inferred from DATABASE_URL
# If specified, it will override auto-detection
type = "sqlite"
# Database connection URL or file path
# The database type is automatically detected from the URL scheme:
# - sqlite:// or .db/.sqlite files β†’ SQLite
# - postgres:// or postgresql:// β†’ PostgreSQL
# - mysql:// β†’ MySQL
# - mariadb:// β†’ MariaDB (uses MySQL protocol)
database_url = "shortlinks.db"
# Database connection pool size
pool_size = 10
# Database connection timeout (seconds)
timeout = 30

[cache]
# Cache type: memory, redis (currently only memory is supported)
type = "memory"
# Default cache expiration time (seconds)
default_ttl = 3600

[cache.redis]
# Redis connection URL
url = "redis://127.0.0.1:6379/"
# Redis key prefix
key_prefix = "shortlinker:"
# Redis connection pool size
pool_size = 10

[cache.memory]
# Memory cache maximum capacity (entries)
max_capacity = 10000

[api]
# Admin API Token (leave empty to disable admin API)
admin_token = ""
# Health check API Token (leave empty to use admin_token)
health_token = ""

[routes]
# Admin API route prefix
admin_prefix = "/admin"
# Health check route prefix
health_prefix = "/health"
# Frontend panel route prefix
frontend_prefix = "/panel"

[features]
# Whether to enable Web admin panel
enable_admin_panel = false
# Random short code length
random_code_length = 6
# Default redirect URL
default_url = "https://esap.cc/repo"

[logging]
# Log level: trace, debug, info, warn, error
level = "info"

Configuration file loading:

When using -c/--config parameter:

  • Uses the specified path (auto-creates if not exists)
  • Example: ./shortlinker -c /path/to/config.toml

When no parameter is specified:

  • Only searches for config.toml in the current directory
  • If not found, uses in-memory default configuration
⁠Environment Variables (Backward Compatible)

Still supports the original environment variable configuration method. Environment variables will override TOML configuration:

VariableDefaultDescription
SERVER_HOST127.0.0.1Listen address
SERVER_PORT8080Listen port
UNIX_SOCKET(empty)Unix socket path (overrides HOST/PORT)
CPU_COUNT(auto)Worker thread count (defaults to CPU cores)
DATABASE_BACKEND(auto-detect)Storage type: sqlite, postgres, mysql, mariadb. OPTIONAL: Auto-detected from DATABASE_URL if not set
DATABASE_URLshortlinks.dbDatabase URL or file path. Supports auto-detection from URL scheme
DATABASE_POOL_SIZE10Database connection pool size
DATABASE_TIMEOUT30Database connection timeout (seconds)
CACHE_TYPEmemoryCache type: memory, redis
CACHE_DEFAULT_TTL3600Default cache TTL in seconds
REDIS_URLredis://127.0.0.1:6379/Redis connection URL
REDIS_KEY_PREFIXshortlinker:Redis key prefix
REDIS_POOL_SIZE10Redis connection pool size
MEMORY_MAX_CAPACITY10000Memory cache max capacity (entries)
ADMIN_TOKEN(empty)Admin API token
HEALTH_TOKEN(empty)Health API token
ADMIN_ROUTE_PREFIX/adminAdmin API route prefix
HEALTH_ROUTE_PREFIX/healthHealth API route prefix
FRONTEND_ROUTE_PREFIX/panelWeb admin panel route prefix
ENABLE_ADMIN_PANELfalseEnable web admin panel
RANDOM_CODE_LENGTH6Random code length
DEFAULT_URLhttps://esap.cc/repoDefault redirect URL
RUST_LOGinfoLog level

Note: The web admin panel is a new feature and may be unstable.

⁠.env Example
# Server - TCP
SERVER_HOST=0.0.0.0
SERVER_PORT=8080
CPU_COUNT=4

# Server - Unix socket
# UNIX_SOCKET=/tmp/shortlinker.sock

# Storage (DATABASE_BACKEND is optional - auto-detected from DATABASE_URL)
# SQLite (file path or URL)
DATABASE_URL=data/links.db
# Or: DATABASE_URL=sqlite://data/links.db

# PostgreSQL
# DATABASE_URL=postgres://user:password@localhost:5432/shortlinker

# MySQL
# DATABASE_URL=mysql://user:password@localhost:3306/shortlinker

# MariaDB
# DATABASE_URL=mariadb://user:password@localhost:3306/shortlinker

# APIs
ADMIN_TOKEN=your_admin_token
HEALTH_TOKEN=your_health_token

# Features
DEFAULT_URL=https://example.com
RANDOM_CODE_LENGTH=8
RUST_LOG=info

⁠Storage Backends

Shortlinker now uses Sea-ORM for database operations, providing:

  • βœ… Atomic upsert operations (prevents race conditions)
  • βœ… Auto-detection from DATABASE_URL (no need to specify DATABASE_BACKEND)
  • βœ… Auto-create SQLite database files if they don't exist
  • βœ… Automatic schema migrations
⁠Supported Databases
  • SQLite (default): Production-ready, recommended for single-node deployments
  • MySQL / MariaDB: Production-ready, recommended for multi-node deployments
  • PostgreSQL: Production-ready, recommended for enterprise deployments
⁠Database URL Examples
# SQLite - Auto-detected
DATABASE_URL=links.db                    # Relative path
DATABASE_URL=/var/lib/shortlinker/links.db  # Absolute path
DATABASE_URL=sqlite://data/links.db      # Explicit SQLite URL

# PostgreSQL - Auto-detected
DATABASE_URL=postgres://user:pass@localhost:5432/shortlinker
DATABASE_URL=postgresql://user:pass@host:5432/db?sslmode=require

# MySQL - Auto-detected
DATABASE_URL=mysql://user:pass@localhost:3306/shortlinker
DATABASE_URL=mysql://user:pass@host:3306/db?charset=utf8mb4

# MariaDB - Auto-detected (uses MySQL protocol)
DATABASE_URL=mariadb://user:pass@localhost:3306/shortlinker

πŸ’‘ Tip: The DATABASE_BACKEND environment variable is now optional. The database type is automatically inferred from your DATABASE_URL. Only specify it if you need to override auto-detection.

⁠Deployment

⁠Reverse Proxy (Nginx)
# TCP port
server {
    listen 80;
    server_name esap.cc;
    location / {
        proxy_pass http://127.0.0.1:8080;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
}

# Unix socket
server {
    listen 80;
    server_name esap.cc;
    location / {
        proxy_pass http://unix:/tmp/shortlinker.sock;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
}
⁠systemd Service
[Unit]
Description=ShortLinker Service
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/shortlinker
ExecStart=/opt/shortlinker/shortlinker
Restart=always
Environment=SERVER_HOST=127.0.0.1
Environment=SERVER_PORT=8080

[Install]
WantedBy=multi-user.target

⁠Development

# Development
cargo run

# Production build
cargo build --release

# Run tests
cargo test

# Code quality
cargo fmt && cargo clippy
  • Web Admin Panel: GUI to manage links in admin-panel/ (docs⁠)
  • Cloudflare Worker: Serverless version in cf-worker/ (docs⁠)

⁠License

MIT License Β© AptS:1547

        οΌοΌžγ€€ フ
       | γ€€_γ€€_|    AptS:1547
     /` γƒŸοΌΏxγƒŽ    β€” shortlinker assistant bot β€”
    /γ€€γ€€γ€€γ€€ |
   /γ€€ ヽ   οΎ‰      Rust / SQLite / Bloom / CLI
   β”‚γ€€γ€€|γ€€|γ€€|
/ ̄|γ€€γ€€ |γ€€|γ€€|
( ̄ヽ__ヽ_)__)
\二)

   γ€Œready to 307 !」

Tag summary

Content type

Image

Digest

sha256:6186acdf1…

Size

7.9 MB

Last updated

about 2 months ago

docker pull e1saps/shortlinker