This is a small project that turns long links into short codes.
Example:
- Long URL:
https://example.com/some/very/long/link - Short code:
aB3x9Q
When you open http://127.0.0.1:8080/aB3x9Q, it sends you to the original long URL.
C-URL_Shortener/
├── src/
│ ├── db.c # saves and reads URLs from SQLite
│ ├── server.c # HTTP server and request handling
│ ├── cache.c # small in-memory cache
│ ├── shortener.c # create short code / expand code
│ └── main.c # app entry point
├── include/ # header files
├── Makefile
└── README.md
- Build the project:
make
- Start the server:
./url_shortener
- Server runs on:
http://127.0.0.1:8080
GET /health→ check server is runningPOST /shorten(body = full URL) → create short codeGET /shorten?url=https://example.com→ create short codeGET /{code}→ redirects to original URL
# health check
curl http://127.0.0.1:8080/health
# create short code (POST)
curl -X POST http://127.0.0.1:8080/shorten -d 'https://example.com'
# create short code (GET)
curl 'http://127.0.0.1:8080/shorten?url=https://example.com'
# open short code (replace abc123)
curl -i http://127.0.0.1:8080/abc123Think of this app like a small counter system:
- A user gives a long URL.
- The app creates a random short code (like
x7Ab12). - It saves this pair (short code + long URL) in a local database.
- Later, when someone visits that short code, the app finds the long URL and redirects.
- HTTP server: listens for requests from browser or
curl. - Concurrency: each request is handled in a separate thread, so many users can use it at the same time.
- Small cache: recently used codes are kept in memory, so repeated lookups are faster.
- SQLite database: permanent storage, so data is not lost when cache is cleared or app restarts.
- Epoll-based asynchronous server for higher scalability
- LRU eviction strategy for cache
- Rate limiting to prevent abuse
- Distributed storage support
- Metrics and observability integration