Skip to content

AptS-1547/shortlinker

Repository files navigation

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.1.7-alpha.1)

Environment

  • OS: Linux
  • CPU: Single-core @ 12th Gen Intel(R) Core(TM) i5-12500
  • Tool: wrk
Type Scenario QPS Peak Cache Hit Bloom Filter DB Access
Cache Hit Hot shortlink (repeated access) 719,997.22 ✅ Yes ✅ Yes ❌ No
Cache Miss Cold shortlink (random access) 610,543.39 ❌ 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+)

Relative Time (Recommended)

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

Configure using environment variables or .env file:

Variable Default Description
SERVER_HOST 127.0.0.1 Listen address
SERVER_PORT 8080 Listen port
UNIX_SOCKET (empty) Unix socket path (overrides HOST/PORT)
CPU_COUNT (auto) Worker thread count (defaults to CPU cores)
STORAGE_BACKEND sqlite Storage type (See Documentation)
DATABASE_URL links.db Database URL (See Documentation)
DEFAULT_URL https://esap.cc/repo Default redirect URL
RANDOM_CODE_LENGTH 6 Random code length
ADMIN_TOKEN (empty) Admin API token
HEALTH_TOKEN (empty) Health API token
ENABLE_ADMIN_PANEL false Serve web admin panel (requires build and ADMIN_TOKEN)
FRONTEND_ROUTE_PREFIX /panel Web admin panel route prefix
RUST_LOG info Log 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
STORAGE_BACKEND=sqlite
DB_FILE_NAME=data/links.db

# 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

  • SQLite (default, v0.1.0+): Production-ready, recommended
  • File Storage: Simple JSON-based storage for development
# SQLite (recommended)
STORAGE_BACKEND=sqlite
DB_FILE_NAME=links.db

# File storage
STORAGE_BACKEND=file
DB_FILE_NAME=links.json

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

Related Modules

  • Web Admin Panel: GUI to manage links in admin-panel/ (docs)
  • Cloudflare Worker: Serverless version in cf-worker/ (docs)

Technical Highlights

  • Cross-Platform Process Management: Smart lock files and signal handling
  • Hot Configuration Reload: Signal-based reload (Unix) and file triggers (Windows)
  • Container-Aware: Special handling for Docker environments
  • Unified Error Handling: Comprehensive error types with automatic conversions
  • Memory Safe: Zero-cost abstractions with thread safety
  • High Test Coverage: Comprehensive unit and integration tests

License

MIT License © AptS:1547

        />  フ
       |  _ _|    AptS:1547
     /` ミ_xノ    — shortlinker assistant bot —
    /     |
   /  ヽ   ノ      Rust / SQLite / Bloom / CLI
   │  | | |
/ ̄|   | | |
( ̄ヽ__ヽ_)__)
\二)

   「ready to 307 !」

🔗 Visit Project Docs 💬 Powered by AptS:1547