Workers + KV : raccourcisseur maison, du débutant à la pratique

Pourquoi mon propre raccourcisseur ?
Pendant près de deux ans, j’utilisais un service de liens courts tiers. Un matin, tous les liens étaient morts — le fournisseur annonçait la fermeture. Les centaines de liens partagés sur les réseaux sociaux renvoyaient en 404.
J’ai alors cherché une solution 100 % à moi : données sous contrôle, personnalisation libre, plus de dépendance à un tiers qui disparaît.
Cloudflare Workers + KV colle parfaitement :
- Quota gratuit très large (100 000 requêtes/jour)
- 200+ nœuds, accès rapide partout
- Déploiement en quelques lignes
- Données que vous gardez aussi longtemps que vous voulez
Cet article explique comment j’ai construit mon raccourcisseur avec Workers + KV : codes personnalisés, statistiques, etc. Le code est inclus — comptez une demi-heure pour être en ligne.
Pourquoi Workers + KV ?
Qu’est-ce que Cloudflare Workers ?
En bref : des fonctions serverless sur le réseau edge de Cloudflare. Vous déployez le code ; il se réplique sur 200+ points de présence. L’utilisateur est routé vers le nœud le plus proche — latence minimale.
Quota gratuit généreux :
- 100 000 requêtes par jour
- 10 ms de CPU par requête
- Largement suffisant pour un usage perso ou une petite équipe
Atouts du stockage KV
KV est la base clé-valeur distribuée de Cloudflare, pensée pour le edge :
- Lecture rapide : médiane ~12 ms grâce au cache edge
- Sync mondiale : propagation globale en ~60 s après écriture
- Quota gratuit : 100 000 lectures et 1 000 écritures par jour
Pour un raccourcisseur, c’est un match naturel :
- Code court = clé, URL = valeur
- Peu d’écritures, beaucoup de lectures
- Accès rapide partout dans le monde
Comparaison avec un service tiers
| Critère | Service tiers | Workers + KV maison |
|---|---|---|
| Données | Chez le tiers | Sous votre contrôle |
| Personnalisation | Fixe | Libre |
| Stabilité | Risque de fermeture | Soutenu par Cloudflare |
| Publicité | Page intermédiaire possible | Aucune |
| Coût | Parfois payant | Quasi gratuit |
| Vitesse | Selon le fournisseur | Réseau edge mondial |
Construire le raccourcisseur de zéro
Assez de théorie — passons à la pratique.
Préparation
1. Compte Cloudflare
Inscrivez-vous sur cloudflare.com — l’offre gratuite suffit.
2. Installer Wrangler CLI
Wrangler est l’outil officiel pour gérer les projets Workers.
npm install -g wrangler
# ou avec yarn
yarn global add wrangler
Puis connectez-vous :
wrangler login
Le navigateur s’ouvre pour l’autorisation — acceptez.
3. Créer le projet
mkdir my-shortlink
cd my-shortlink
wrangler init
Suivez les invites ; un projet JavaScript convient (TypeScript aussi).
Étape 1 : créer l’espace de noms KV
Le KV exige d’abord un « namespace », un peu comme une table dans une base.
# Production
wrangler kv namespace create SHORTLINKS
# Prévisualisation (tests locaux)
wrangler kv namespace create SHORTLINKS --preview
Vous obtenez deux ID, par exemple :
{ binding = "SHORTLINKS", id = "abc123..." }
{ binding = "SHORTLINKS", preview_id = "def456..." }
Important : notez ces ID pour la suite.
Éditez wrangler.toml :
name = "my-shortlink"
main = "src/index.js"
compatibility_date = "2025-12-01"
# Liaison KV
kv_namespaces = [
{ binding = "SHORTLINKS", id = "votre ID production", preview_id = "votre ID preview" }
]
binding = "SHORTLINKS" permet d’accéder au KV via env.SHORTLINKS dans le code.
Étape 2 : fonctionnalité de base
Ouvrez src/index.js :
export default {
async fetch(request, env) {
const url = new URL(request.url);
const path = url.pathname.slice(1); // sans le / initial
if (path === '') {
return new Response('Bienvenue sur le service de liens courts !', { status: 200 });
}
if (request.method === 'GET') {
const targetUrl = await env.SHORTLINKS.get(path);
if (targetUrl) {
return Response.redirect(targetUrl, 301);
} else {
return new Response('Lien court introuvable', { status: 404 });
}
}
if (request.method === 'POST') {
try {
const body = await request.json();
const { url: targetUrl, code } = body;
if (!targetUrl) {
return new Response('Paramètre url manquant', { status: 400 });
}
const shortCode = code || generateRandomCode();
const existing = await env.SHORTLINKS.get(shortCode);
if (existing) {
return new Response('Code court déjà utilisé', { status: 409 });
}
await env.SHORTLINKS.put(shortCode, targetUrl);
return new Response(JSON.stringify({
shortCode,
shortUrl: `${url.origin}/${shortCode}`,
targetUrl
}), {
status: 201,
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
return new Response('Format de requête invalide', { status: 400 });
}
}
return new Response('Méthode non autorisée', { status: 405 });
}
};
function generateRandomCode(length = 6) {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let code = '';
for (let i = 0; i < length; i++) {
code += chars.charAt(Math.floor(Math.random() * chars.length));
}
return code;
}
Logique :
GET: visite deyourdomain.com/abc123→ lecture KV → redirection 301POST:url+codeoptionnel ; génération aléatoire si pas de code → écriture KVgenerateRandomCode: 6 caractères alphanumériques
Étape 3 : tests locaux
wrangler dev
Serveur local, en général http://localhost:8787.
Créer un lien :
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
Réponse :
{
"shortCode": "aBc123",
"shortUrl": "http://localhost:8787/aBc123",
"targetUrl": "https://example.com"
}
Tester la redirection : ouvrez http://localhost:8787/aBc123 — vous devez arriver sur https://example.com.
Si tout fonctionne, la base est OK.
Étape 4 : code court personnalisé
Le code accepte déjà un code dans le POST :
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "code": "my-link"}'
Pour plus de robustesse, validez le format :
if (code) {
if (!/^[a-zA-Z0-9-]+$/.test(code)) {
return new Response('Format de code invalide (lettres, chiffres, tirets uniquement)', { status: 400 });
}
if (code.length < 3 || code.length > 20) {
return new Response('Longueur du code : entre 3 et 20 caractères', { status: 400 });
}
}
Cela évite des codes bizarres (caractères spéciaux, longueur excessive).
Étape 5 : statistiques de visites
Souvent, on veut aussi le nombre de clics par lien.
Idée :
- À chaque visite : incrémenter un compteur
- Stocker sous
stats:{shortCode}dans le KV
Modifiez la partie GET :
if (request.method === 'GET') {
const targetUrl = await env.SHORTLINKS.get(path);
if (targetUrl) {
const statsKey = `stats:${path}`;
env.SHORTLINKS.get(statsKey).then(count => {
const newCount = (parseInt(count) || 0) + 1;
env.SHORTLINKS.put(statsKey, newCount.toString());
});
return Response.redirect(targetUrl, 301);
} else {
return new Response('Lien court introuvable', { status: 404 });
}
}
Endpoint de consultation :
if (path.startsWith('stats/')) {
const shortCode = path.slice(6);
const statsKey = `stats:${shortCode}`;
const count = await env.SHORTLINKS.get(statsKey);
return new Response(JSON.stringify({
shortCode,
visits: parseInt(count) || 0
}), {
headers: { 'Content-Type': 'application/json' }
});
}
Accès : http://localhost:8787/stats/abc123 pour le nombre de visites.
Note : le KV n’est pas atomique — en forte concurrence, le compteur peut dériver. Pour de la précision stricte, utilisez Durable Objects. Pour un usage perso, cette approche suffit souvent.
Étape 6 : déploiement en production
wrangler deploy
URL du type https://my-shortlink.your-subdomain.workers.dev — votre raccourcisseur, accessible mondialement.
Domaine personnalisé (optionnel) :
Avec un domaine (ex. short.example.com) :
- Workers & Pages dans le Dashboard
- Sélectionnez votre Worker
- Settings > Triggers
- Ajoutez un Custom Domain
Exemple de lien : https://short.example.com/abc123.
Fonctions avancées
1. Création par lot
if (request.method === 'POST' && url.pathname === '/batch') {
try {
const body = await request.json();
const links = body.links;
if (!Array.isArray(links)) {
return new Response('links doit être un tableau', { status: 400 });
}
const results = [];
for (const link of links) {
const { url: targetUrl, code } = link;
const shortCode = code || generateRandomCode();
const existing = await env.SHORTLINKS.get(shortCode);
if (!existing) {
await env.SHORTLINKS.put(shortCode, targetUrl);
results.push({ shortCode, targetUrl, success: true });
} else {
results.push({ shortCode, targetUrl, success: false, error: 'Code court déjà utilisé' });
}
}
return new Response(JSON.stringify({ results }), {
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
return new Response('Format de requête invalide', { status: 400 });
}
}
Appel :
curl -X POST http://localhost:8787/batch \
-H "Content-Type: application/json" \
-d '{
"links": [
{"url": "https://example1.com", "code": "link1"},
{"url": "https://example2.com"}
]
}'
2. Expiration (TTL)
Le KV accepte un TTL :
await env.SHORTLINKS.put(shortCode, targetUrl, {
expirationTtl: 86400 // suppression après 24 h (secondes)
});
TTL choisi par l’utilisateur :
const { url: targetUrl, code, ttl } = body;
const options = {};
if (ttl) {
options.expirationTtl = parseInt(ttl);
}
await env.SHORTLINKS.put(shortCode, targetUrl, options);
3. Contrôle d’accès
Limiter la création de liens avec un token API :
// wrangler.toml
# [vars]
# API_TOKEN = "your-secret-token"
if (request.method === 'POST') {
const token = request.headers.get('Authorization');
if (token !== `Bearer ${env.API_TOKEN}`) {
return new Response('Non autorisé', { status: 401 });
}
// ... création
}
Appel avec token :
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-secret-token" \
-d '{"url": "https://example.com"}'
4. Limitation de débit (anti-abus)
const clientIp = request.headers.get('CF-Connecting-IP');
const rateLimitKey = `ratelimit:${clientIp}`;
const count = await env.SHORTLINKS.get(rateLimitKey);
if (parseInt(count) >= 10) {
return new Response('Trop de requêtes, réessayez plus tard', { status: 429 });
}
const newCount = (parseInt(count) || 0) + 1;
await env.SHORTLINKS.put(rateLimitKey, newCount.toString(), {
expirationTtl: 3600
});
Limite : 10 créations par IP et par heure.
Performance et bonnes pratiques
Optimisations
1. Cache
Le KV est déjà rapide (~12 ms médiane). Cache mémoire optionnel dans le Worker :
const cache = new Map();
const targetUrl = cache.get(path) || await env.SHORTLINKS.get(path);
if (targetUrl) {
cache.set(path, targetUrl);
return Response.redirect(targetUrl, 301);
}
La mémoire Worker n’est pas persistante — perdue au redémarrage.
2. Réduire les écritures KV
Quota : 1 000 écritures/jour. Stats à chaque clic = risque de dépassement.
Options : Durable Objects (atomique), écrire tous les N clics, ou Cloudflare Analytics Engine.
3. CORS
Pour appels depuis un frontend :
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
};
if (request.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
return new Response(body, {
headers: { ...headers, ...corsHeaders }
});
Coûts
Quota gratuit :
- 100 000 requêtes Workers/jour
- KV : 100 000 lectures, 1 000 écritures/jour
- 10 ms CPU par requête
Hors quota (Workers Paid, à partir de 5 $/mois) :
- 0,50 $ / million de requêtes
- KV lecture : 0,50 $ / million
- KV écriture : 5,00 $ / million
- Stockage : 0,50 $ / Go/mois
Usage perso : rarement au-delà du gratuit. Petite équipe : souvent OK avec des dizaines de milliers de visites/jour.
Économiser les requêtes :
- 301 (cache navigateur) plutôt que 302
- Pages statiques sur Workers Pages
- TTL pour liens expirés
Sécurité
1. Liens malveillants
Service public = risque d’abréger des URLs dangereuses.
- Token API
- Liste noire de domaines
- Journal IP du créateur
2. Collisions
Vérifiez l’existence malgré l’espace énorme :
const existing = await env.SHORTLINKS.get(shortCode);
if (existing) {
return new Response('Code court déjà utilisé', { status: 409 });
}
3. URL cible
Liste blanche :
const allowedDomains = ['example.com', 'mywebsite.com'];
const targetDomain = new URL(targetUrl).hostname;
if (!allowedDomains.some(d => targetDomain.endsWith(d))) {
return new Response('Domaine cible non autorisé', { status: 403 });
}
Mon retour d’expérience
Plusieurs mois d’usage :
Avantages :
- Rapide : latence souvent < 50 ms, bien mieux que mon ancien tiers
- Stable : réseau Cloudflare, quasi pas de panne
- Serein : déployé une fois, montée en charge automatique
- Gratuit : quelques milliers de requêtes/jour, dans le quota
Écueils :
- Latence d’écriture KV : cohérence finale, synchro globale en dizaines de secondes — peu gênant (on crée rarement puis on partage tout de suite)
- Stats imprécises : pas d’atomique KV ; Durable Objects si vous voulez de la précision (plus cher hors quota)
Pistes :
- Dashboard Workers Pages
- Cloudflare Analytics (sources, géo)
- QR codes pour le partage hors ligne
Synthèse
Workers + KV pour un raccourcisseur : rapide et économique. Moins de 100 lignes de cœur, un wrangler deploy, et vos données restent chez vous.
Si le besoin vous parle, essayez — le code est là, une demi-heure suffit souvent.
Rappel des étapes :
- Compte Cloudflare + Wrangler
- Namespace KV +
wrangler.toml - GET (redirection) + POST (création)
- Tests locaux, déploiement
Ensuite : stats, lot, expiration… le code est à vous — c’est satisfaisant.
Des questions ? Laissez un commentaire — bon déploiement !
Construire un raccourcisseur avec Cloudflare Workers + KV
Mise en place complète : création de liens, redirection, statistiques de visites, en ligne en une demi-heure
⏱️ Estimated time: 30 min
- 1
Step 1: Préparation : compte Cloudflare et Wrangler CLI
Étape 1 : compte Cloudflare
• Inscrivez-vous sur cloudflare.com — l'offre gratuite suffit
Étape 2 : installer Wrangler CLI
• Wrangler est l'outil officiel en ligne de commande pour gérer les projets Workers
• Exécutez : npm install -g wrangler
• Ou : yarn global add wrangler
• Puis connectez-vous : wrangler login
• Le navigateur s'ouvre pour l'autorisation — acceptez
Étape 3 : créer le projet
• mkdir my-shortlink
• cd my-shortlink
• wrangler init
• Suivez les invites ; choisissez un projet JavaScript (TypeScript possible aussi) - 2
Step 2: Créer l'espace de noms KV et configurer wrangler.toml
Créer l'espace de noms KV :
Méthode 1 : Dashboard Cloudflare
• Workers & Pages → KV
• Create a namespace
• Nom (ex. SHORTLINKS), puis créer
Méthode 2 : ligne de commande
• wrangler kv:namespace create SHORTLINKS
Configurer wrangler.toml :
À la fin du fichier, ajoutez la liaison KV :
[[kv_namespaces]]
binding = "SHORTLINKS"
id = "votre ID d'espace de noms"
Dans le code, accédez au KV via env.SHORTLINKS - 3
Step 3: Code cœur : création de liens et redirection
Fonctions principales :
1. Génération du code court :
• Code personnalisé ou aléatoire
• 6 caractères alphanumériques possibles
• 62^6 ≈ 56,8 milliards de combinaisons — collisions rares
2. Stockage KV :
• Code court = clé, URL d'origine = valeur
• Métadonnées possibles (date de création, nombre de visites, etc.)
3. Redirection :
• GET : lire l'URL d'origine dans le KV
• Réponse 302 vers l'URL cible
4. Statistiques :
• Compteur et horodatage des visites
• Stockables dans les métadonnées KV
Exemples :
• GET (redirection) : code court depuis le chemin, lecture KV, 302 si trouvé, 404 sinon
• POST (création) : URL cible + code court optionnel, génération, vérification collision, écriture KV, retour de l'URL courte - 4
Step 4: Tests locaux et déploiement en production
Tests locaux :
1. wrangler dev pour le serveur local
2. Tester création et redirection
Avec curl :
• Créer un lien :
curl -X POST http://localhost:8787/create -H "Content-Type: application/json" -d '{"url":"https://example.com"}'
• Visiter le lien court :
curl -L http://localhost:8787/abc123
(redirection vers l'URL d'origine)
Déploiement :
• wrangler deploy
• Wrangler déploie le Worker sur Cloudflare
• URL du type : your-worker-name.your-subdomain.workers.dev
• Votre raccourcisseur est en ligne ! - 5
Step 5: Fonctions avancées et sécurité
Avancé : 1) statistiques (compteur et horodatage dans les métadonnées KV, mise à jour à chaque visite) ; 2) expiration (TTL, lien invalide après échéance) ; 3) création par lot ; 4) interface d'admin (Dashboard simple via Workers Pages). Sécurité : 1) liens malveillants (token API, liste noire de domaines, IP du créateur) ; 2) collisions de codes (vérifier l'existence avant création malgré l'espace énorme) ; 3) URL cible (liste blanche de domaines autorisés). Économiser les requêtes : redirection 301 (cache navigateur) plutôt que 302 ; pages statiques sur Workers Pages ; TTL pour nettoyer les liens expirés.
FAQ
Pourquoi héberger son propre raccourcisseur ? Quels avantages Workers + KV ?
Avantages Workers + KV :
• Quota gratuit très large (100 000 requêtes/jour)
• 200+ nœuds edge, latence faible partout
• Quelques lignes de code pour démarrer
• Données sous votre contrôle, durée de conservation à votre choix
Comparaison avec un tiers :
• Données (chez le tiers vs entièrement chez vous)
• Personnalisation (fixe vs libre)
• Stabilité (risque de fermeture vs Cloudflare)
• Publicité (page intermédiaire possible vs aucune)
• Coût (payant possible vs quasi gratuit)
• Vitesse (selon le fournisseur vs réseau edge mondial)
Quels avantages du stockage KV pour un raccourcisseur ?
Atouts KV :
• Lecture rapide, médiane ~12 ms (cache sur les nœuds edge)
• Synchronisation mondiale : propagation globale en ~60 s après écriture
• Quota gratuit : 100 000 lectures et 1 000 écritures par jour
Pour les liens courts, le KV est idéal :
• Code court = clé, URL = valeur
• Profil lecture-intensive (peu de créations, beaucoup de clics)
• Distribution mondiale
Quotas gratuits :
• Workers : 100 000 requêtes/jour
• KV : 100 000 lectures, 1 000 écritures/jour
• Suffisant pour un usage perso ; souvent OK pour une petite équipe (dizaines de milliers de visites/jour)
Au-delà du gratuit (Workers Paid, à partir de 5 $/mois) :
• 0,50 $ / million de requêtes Workers
• 0,50 $ / million de lectures KV
• 5,00 $ / million d'écritures KV
• 0,50 $ / Go/mois de stockage KV
Comment construire un raccourcisseur de zéro ? Quelles étapes ?
1. Compte Cloudflare (cloudflare.com, offre gratuite)
2. Wrangler (npm install -g wrangler, puis wrangler login)
3. Projet (mkdir my-shortlink, cd, wrangler init)
KV et configuration :
• Dashboard : Workers & Pages → KV → Create a namespace (ex. SHORTLINKS)
• Ou CLI : wrangler kv:namespace create SHORTLINKS
wrangler.toml :
• Ajouter la liaison KV en fin de fichier
• Accès via env.SHORTLINKS dans le code
Code cœur :
GET (redirection) :
• Code court depuis le chemin
• Lecture de l'URL dans le KV
• 302 si trouvé, 404 sinon
POST (création) :
• URL cible + code court optionnel
• Génération aléatoire si pas de code fourni
• Vérification d'existence (anti-collision)
• Écriture KV, retour de l'URL courte
Test et déploiement :
• wrangler dev en local
• wrangler deploy en production
Comment implémenter les fonctions cœur du raccourcisseur ?
1) Code court :
• Personnalisé ou aléatoire
• 6 caractères alphanumériques, 62^6 ≈ 56,8 milliards — collisions rares
2) Stockage KV :
• Clé = code court, valeur = URL
• Métadonnées : date de création, compteur, etc.
3) Redirection :
• GET : lecture KV, 302 vers l'URL cible
4) Statistiques :
• Compteur et horodatage
• Métadonnées KV, incrément à chaque visite
Exemples de flux :
GET :
• Code court depuis le chemin
• Lecture KV → 302 ou 404
POST :
• URL + code optionnel
• Génération si besoin
• Vérification collision
• put KV, retour URL courte
Avancé : statistiques, expiration, lot, Dashboard Workers Pages
Quelles précautions de sécurité pour un raccourcisseur ?
1) Liens malveillants :
• Service ouvert = risque d'abréger des sites dangereux
• Recommandations :
- Token API
- Liste noire de domaines connus
- Journaliser l'IP du créateur
2) Collisions de codes :
• 62^6 combinaisons — rare, mais vérifier quand même :
const existing = await env.SHORTLINKS.get(shortCode);
if (existing) {
return new Response('Code court déjà utilisé', { status: 409 });
}
3) URL cible :
• Liste blanche de domaines :
const allowedDomains = ['example.com', 'mywebsite.com'];
const targetDomain = new URL(targetUrl).hostname;
if (!allowedDomains.some(d => targetDomain.endsWith(d))) {
return new Response('Domaine cible non autorisé', { status: 403 });
}
Économiser les requêtes :
• 301 plutôt que 302 (cache navigateur)
• Pages statiques sur Workers Pages
• TTL pour liens expirés
Retour d'expérience : avantages et limites ?
Avantages :
• Rapide (latence mondiale souvent < 50 ms, bien mieux que mon ancien tiers)
• Stable (réseau Cloudflare, rarement de panne)
• Serein (déployé une fois, montée en charge automatique)
• Gratuit (quelques milliers de requêtes/jour, dans le quota)
Écueils :
• Latence d'écriture KV (cohérence finale, dizaines de secondes pour la synchro globale — peu gênant pour les liens courts, création puis accès différé)
• Stats imprécises (pas d'opérations atomiques KV ; en forte concurrence, compter via Durable Objects si précision requise — plus coûteux hors quota)
Pistes :
• Dashboard Workers Pages
• Cloudflare Analytics (sources, géo)
• Génération de QR codes pour le partage hors ligne
9 min de lecture · Publié le: 1 déc. 2025 · Mis à jour le: 27 juil. 2026
Cloudflare Full Stack
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Frais de trafic S3 à 1 000 $/mois ? Migrer vers R2 en 3 étapes et économiser 90 % (cas réels)
Les frais de trafic S3 font exploser la facture ? Guide pas à pas pour migrer vers Cloudflare R2, zéro egress, économies annuelles de 10 896 $+. Comparaison de 3 méthodes, tests de compatibilité API, tutoriel en 30 minutes et calcul de coûts réels.
Partie 14 sur 23
Suivant
Clé API exposée côté frontend ? Proxy Workers en 5 minutes, 100 000 requêtes gratuites/jour
Appeler une API directement depuis le frontend expose vos clés et peut entraîner des frais frauduleux. Apprenez à déployer un proxy API gratuit avec Cloudflare Workers en 5 minutes : clé stockée côté serveur, 100 000 requêtes gratuites par jour, et résolution CORS incluse.
Partie 16 sur 23



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire