You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docker compose up -d
# Server starts on http://localhost:8080
Manual
go build -o filestore-server .export MYSQL_DSN="root:root@tcp(127.0.0.1:3306)/fileserver?charset=utf8mb4&parseTime=True&loc=Local"export REDIS_ADDR="127.0.0.1:6379"
./filestore-server
Configuration
All configuration via environment variables (see config/config.go):
Variable
Default
Description
MYSQL_DSN
root:root@tcp(127.0.0.1:3306)/fileserver?...
MySQL connection string
REDIS_ADDR
127.0.0.1:6379
Redis address
REDIS_PASS
(empty)
Redis password
REDIS_DB
0
Redis DB number
SERVER_ADDR
:8080
HTTP listen address
UPLOAD_DIR
./uploads
Upload directory
CHUNK_DIR
./chunks
Chunk directory
API Endpoints
File Operations (🔒 Require Auth)
Method
Route
Description
GET
/file/upload
Serve upload page
POST
/file/upload
Upload file (supports fast-upload)
GET
/file/upload/suc
Upload success page
GET
/file/meta
Get file metadata by hash
GET
/file/query
List all files
GET
/file/download
Download file by hash
POST
/file/update
Rename file (op=0)
POST
/file/delete
Soft delete file
POST
/file/upload/chunk
Upload single chunk
GET
/file/upload/status
Check uploaded chunk indices
POST
/file/upload/merge
Merge chunks into final file
User Operations
Method
Route
Auth
Rate Limit
Description
POST
/user/signup
No
Yes
Register user
POST
/user/signin
No
Yes
Login, get token
GET
/user/info
Yes
No
Get user info
System
Method
Route
Description
GET
/healthz
Health check (Redis ping)
Architecture Notes
Auth: Cookie-based session. HTTPInterceptor wraps all file routes. Tokens are 64-char hex from crypto/rand, expire in 24h. Cookies have SameSite=Strict.
Storage: MySQL is the single source of truth. Redis used for caching (file hash → location) and chunk tracking (Redis Sets).
Password: bcrypt with DefaultCost. No static salt.
Chunked upload: Chunks saved to ./chunks/<filehash>/<index>, tracked in Redis Sets. Merge concatenates into ./uploads/, cleans up chunks.
Fast upload: Checks Redis cache then MySQL for existing file hash — returns immediately if found.
Graceful shutdown: Listens for SIGINT/SIGTERM, drains connections with 10s timeout.
Soft delete:FileDeleteHandler sets status=2 in MySQL, does not remove file from disk.
Rate limiting: IP-based token bucket on /user/signup and /user/signin (5 req/s, burst 10).
Logging: Structured JSON logging via log/slog. Levels: Info, Warn, Error.
Testing
go test ./... # Run all tests
go test ./util/... # Run util tests only
go test ./handler/... # Run handler tests only