Créer un raccourcisseur d'URL avec Nitro et Cloudflare Pages
Dans cet article, nous allons développer un raccourcisseur d'URL en utilisant Nitro et le déployer sur Cloudflare Pages.
Le code source est accessible sur url-shortener
Nitro représente une nouvelle génération de kit d'outils serveur. Il nous permet de construire des serveurs web avec toutes les fonctionnalités nécessaires et de les déployer à notre convenance.
Cloudflare Pages est une plateforme conçue pour construire et héberger des sites web sur le edge. Elle prend en charge des services comme KV pour créer des applications complètes et à état.
Notre projet est un raccourcisseur d'URL simple qui facilite la conversion d'une longue URL en une version raccourcie. Nous allons utiliser le Cloudflare KV pour stocker les URL et le serveur Nitro pour gérer les requêtes.
Nous allons utiliser :
- unstorage pour rationaliser le processus de développement en abstraire la couche KV, éliminant ainsi le besoin du Cloudflare Wrangler CLI.
- ohash pour générer un hash à partir de l'URL afin de prévenir les collisions.
- nanojsx pour construire les pages HTML en utilisant TSX.
- pico.css pour styliser l'application.
Initialisation du Projet
Tout d'abord, créez un nouveau projet Nitro :
npx giget@latest nitro url-shortener
Ensuite, naviguez jusqu'au projet et installez les dépendances requises :
cd url-shortener
npm install
Démarrez le serveur de développement pour voir la page par défaut de Nitro :
npm run dev
Ouvrez votre navigateur et visitez http://localhost:3000 pour vérifier la fonctionnalité.
Construction du Raccourcisseur d'URL
Dans un premier temps, installez les paquets nécessaires :
npm install ohash nano-jsx
Générer une URL Raccourcie
Créez une route nommée index.get.tsx dans le répertoire server/routes. Cela servira de page d'accueil de notre raccourcisseur d'URL où les utilisateurs peuvent générer une URL raccourcie à partir d'une longue.
import { h, Helmet, renderSSR } from 'nano-jsx' // le `h` est crucial ici
import { withTemplate } from '../resources/template'
export default defineLazyEventHandler(() => {
const App = () => {
return (
<div>
<Helmet>
<title>Raccourcisseur d'URL avec Nitro</title>
</Helmet>
<h2>Raccourcir une URL</h2>
<form action="/create" method="POST">
<input type="url" name="url" placeholder="URL à raccourcir" autocomplete="off" />
<button type="submit">Créer</button>
</form>
</div>
)
}
const app = renderSSR(<App />)
const { body, head } = Helmet.SSR(app)
const page = withTemplate({
body,
head,
})
return defineEventHandler(() => {
return page
})
})
Cette route présentera un formulaire permettant aux utilisateurs de saisir une URL à raccourcir. Lors de la soumission du formulaire, une requête POST est envoyée à la route /create.
Un gestionnaire d'événements paresseux est utilisé pour générer la vue une seule fois, lorsque la requête atteint le serveur. La réponse est ensuite mise en cache en mémoire et réutilisée pour les requêtes futures, réduisant ainsi la charge computationnelle.
La fonction withTemplate sert d'utilitaire que nous devons construire.
interface LayoutProps {
body: string
head: string[]
}
export function withTemplate(props: LayoutProps) {
const { head, body } = props
return /* html */`<html>
<head>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
/>
${head.join('\n')}
</head>
<body>
<header class="container">
<h1>
<a href="/">Raccourcisseur d'URL avec Nitro</a>
</h1>
</header>
<main class="container">
${body}
</main>
</body>
</html>`
}
Ceci est un simple template de chaîne où nous incorporons le contenu de l'en-tête et du corps générés par nano-jsx.
Stockage de l'URL
Avant de procéder, installez zod pour valider le corps de la requête.
npm install zod
Créez la route /create pour gérer la requête POST et stocker l'URL dans le KV. Cette route est étiquetée create.post.tsx et se trouve dans le répertoire server/routes.
import { h, Helmet, renderSSR } from 'nano-jsx'
import { hash } from 'ohash'
import { z } from 'zod' // le `h` est essentiel ici
import { withTemplate } from '../resources/template'
export default defineEventHandler(async (event) => {
const body = await readValidatedBody(event, z.object({
url: z.string().url(),
}).parse)
const requestURL = getRequestURL(event)
const id = hash(body.url)
const shortenURL = new URL(`/${id}`, requestURL).href
await useStorage('data').setItem(id, body.url)
const App = () => {
return (
<div>
<Helmet>
<title>Créé</title>
</Helmet>
<h2>Créé et prêt</h2>
<input
type="text"
value={shortenURL}
autofocus
/>
</div>
)
}
const app = renderSSR(<App />)
const { body: nanoBody, head } = Helmet.SSR(app)
return withTemplate({
body: nanoBody,
head,
})
})
Dans ce segment, nous utilisons la fonction readValidatedBody pour valider le corps de la requête. Cela assure que le champ url est une URL légitime, sinon une erreur est générée.
Nous récupérons l'URL de la requête en utilisant la fonction getRequestURL de h3.
Le hash est créé à partir de l'URL du corps en utilisant la fonction hash de ohash, garantissant une génération de hash cohérente pour éviter les collisions.
L'URL est stockée dans le KV en utilisant la fonction useStorage de unstorage, employant le namespace data pour stocker les URL, préconfiguré pour notre utilisation.
Merci de me lire ! Je m’appelle Estéban, et j’adore écrire sur le développement web et le parcours humain qui l’entoure.
Je code depuis plusieurs années et j’apprends encore de nouvelles choses chaque jour. Je partage ce que j’apprends, car j’aurais aimé disposer de ressources claires et complètes lorsque j’ai commencé la programmation.
Si vous avez une question ou souhaitez discuter, laissez un commentaire ci-dessous ou contactez-moi sur mes profils sociaux.
J’espère que cet article vous a appris quelque chose d’utile. Partagez-le, laissez un commentaire ou ajoutez une réaction si c’est le cas. Soutenir mon travail sur GitHub.
Suivez-moi
Estéban Soubiran
Ingénieur logiciel, conférencier et passionné d'open source.
Discussions
Chargement des discussions...
Ajouter un commentaire
Vérification de votre session...