A URL shortener is a sevice where you register a long or complicated URL and receive a compact and simple URL which redirects to the original URL. This is a demonstration of a highly scalable URL shortener written in Rust. The goal is to be able to support millions of redirects per second with limited resources.
This is how you run url-shortener locally:
docker run --rm -d -e POSTGRES_PASSWORD=verrahsecret -p 127.0.0.1:5432:5432 postgres
env POSTGRES_USERNAME=postgres POSTGRES_PASSWORD=verrahsecret POSTGRES_DB=postgres cargo run
Remember to prepare the database, see below. You can run psql "host=localhost user=postgres password=verrahsecret" -c '<SQL>
to achieve this.
The Dockerfile contains the full build instructions if you want to build the container locally.
docker build -t ghcr.io/bittrance/url-shortener .
Register a new token:
curl -X POST -H 'Content-Type: application/json' --data-binary '{"target": "https://www.google.com"}' http://localhost:8080/admin/tokens
If you then verify that the API returns a response with status code 307 for this token.
curl -v http://localhost:8080/<token>
The URL shortener is published to ghcr.io. You can run it as an OCI container. You want to expose its port 8080 in order to reach the forwarder on HTTP and port 4433 to reach the forwarder on HTTPS.
docker run -p 8080:8080 -p 4433:4433 ghcr.io/bittrance/url-shortener
url-shortener is configured using env vars:
Variables | Description |
---|---|
BIND_ADDRESS | Address to bind to. Defaults to 0.0.0.0. |
POOL_SIZE | Max database connections. Defaults to 5. |
POSTGRES_HOST | PostgreSQL hostname. Defaults to 127.0.0.1. |
POSTGRES_PORT | PostgreSQL port. Defaults to 5432. |
POSTGRES_DB | PostgreSQL database. Defaults to urlshortener. |
POSTGRES_USERNAME | PostgreSQL username. Defaults to url-shortener. |
POSTGRES_PASSWORD | PostgreSQL password. Required parameter. |
KEY_FILE | Path to a private key in PEM format. |
CERTCHAIN_FILE | Path to a certificate chain in PEM format. |
url-shortener does not yet provision its own tables. You need to apply the following DDL:
CREATE TABLE tokens (
token CHAR(8) UNIQUE NOT NULL,
target VARCHAR(1024) NOT NULL,
PRIMARY KEY(token)
);
CREATE TABLE counts (
token CHAR(8),
target VARCHAR(1024),
timestamp BIGINT,
count BIGINT
);
You can deploy a simple 3-node setup with Kind.
kind create cluster --config kubernetes/kind-cluster.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
kubectl wait --namespace ingress-nginx \ [|url-shortener]
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=90s
kubectl create namespace url-shortener
kubectl apply --namespace url-shortener -f kubernetes/url-shortener.yaml