01 - Anatomie d'une URL
Ce que tu vas apprendre
- Les 7 composants d'une URL et leur rôle exact
- La différence entre encodeURI et encodeURIComponent
- Comment fonctionne l'API URL en JavaScript
- Pourquoi les domaines internationaux passent par le punycode
- La distinction entre URL absolue et URL relative
Prerequisites
Avoir lu l'article 00 - Introduction ou savoir ce qu'est HTTP.
On tape des URL tous les jours. Des centaines par semaine si on compte les requêtes API, les redirections, les liens dans le code. Et pourtant, je suis pret a parier que la moitie des devs ne savent pas exactement ou finit le host et ou commence le path dans une URL avec un port non standard et des query parameters encodes.
Je le sais parce que j'ai moi-meme galere pendant des annees avec l'encoding des espaces dans les URL. %20 ou + ? La réponse est : ca depend ou tu es. Et c'est exactement le genre de subtilite que cet article va clarifier.
Les 7 morceaux d'une URL
Prenons cette URL et decoupons-la :
https://api.example.com:8443/v2/users?role=admin&active=true#section-3
| Composant | Valeur | Rôle |
|---|---|---|
| Scheme | https |
Le protocole a utiliser |
| Host | api.example.com |
La machine cible |
| Port | 8443 |
Le port TCP (443 par défaut pour HTTPS) |
| Path | /v2/users |
La ressource demandee |
| Query | role=admin&active=true |
Les paramètres |
| Fragment | section-3 |
L'ancre cote client |
Le fragment (#section-3) n'est jamais envoye au serveur. C'est purement cote client. Si tu mets des infos sensibles dans un fragment en pensant que le serveur ne les voit pas, tu as raison -- mais le JavaScript de la page, lui, y a acces.
Le scheme, c'est pas juste "http" ou "https"
On pense souvent que le scheme est soit http, soit https. En réalité, le scheme identifié le protocole ou le handler. Tu connais ftp://, mailto:, tel:, file://. Mais il y a aussi data: pour les donnees inline et blob: pour les objets en mémoire dans le navigateur.
Pour HTTP, la regle est simple :
http -> port 80 par defaut, pas de chiffrement
https -> port 443 par defaut, TLS obligatoire
Host et port : les subtilites
Le host peut etre un nom de domaine (example.com) ou une adresse IP (192.168.1.1). Pour IPv6, on met l'adresse entre crochets :
http://[::1]:3000/api/health
Le port est optionnel quand c'est le port par défaut du scheme. https://example.com et https://example.com:443 sont équivalents. Mais attention : pour le navigateur et les cookies, le port fait partie de l'origine. localhost:3000 et localhost:3001 sont deux origines différentes.
Le path : plus qu'un chemin de fichier
Le path ressemble a un chemin de fichier Unix, mais c'est une abstraction. /users/42 ne signifie pas qu'il y a un dossier users avec un fichier 42 sur le disque. C'est le serveur qui décidé comment interpréter le path.
Quelques conventions courantes :
/api/v2/users -> collection de ressources
/api/v2/users/42 -> ressource specifique
/api/v2/users/42/posts -> sous-ressource
Le path est case-sensitive (sauf si le serveur décidé autrement). /Users et /users sont deux chemins différents en theorie.
Query string : le chaos organise
La query string commence apres le ? et contient des paires clé-valeur separees par & :
?search=hello+world&page=2&sort=name&order=asc
Quelques trucs a savoir :
- L'ordre des paramètres n'a pas de signification définie par la spec (mais certains serveurs en dependent)
- Une clé peut apparaître plusieurs fois :
?tag=js&tag=httpest valide - Un paramètre peut ne pas avoir de valeur :
?debugest valide - Le
+dans une query string represente un espace (convention historique des formulaires HTML)
L'encoding : le vrai cauchemar
Pourquoi est-ce qu'on voit %20 parfois et + d'autres fois pour un espace ? Parce que deux standards coexistent :
Percent-encoding (RFC 3986) : chaque caractère special est encode en %XX ou XX est le code hexadecimal. Un espace devient %20. C'est le standard pour les URL en général.
application/x-www-form-urlencoded : les espaces deviennent +, et les autres caractères speciaux sont percent-encodes. C'est le format des formulaires HTML.
En JavaScript, tu as deux fonctions :
javascript// Pour encoder un composant d'URL (une valeur de parametre)
encodeURIComponent("hello world & co")
// "hello%20world%20%26%20co"
// Pour encoder une URL complete (ne touche pas aux separateurs)
encodeURI("https://example.com/path with spaces")
// "https://example.com/path%20with%20spaces"
La regle : utilise toujours encodeURIComponent pour les valeurs de paramètres. encodeURI ne touche pas aux &, =, #, ce qui peut créer des failles si tu y mets des donnees utilisateur.
L'API URL en JavaScript
Depuis quelques annees, on a une API propre pour manipuler les URL sans faire du bricolage de chaînes :
javascriptconst url = new URL("https://api.example.com:8443/v2/users?role=admin#top");
url.protocol // "https:"
url.hostname // "api.example.com"
url.port // "8443"
url.pathname // "/v2/users"
url.search // "?role=admin"
url.hash // "#top"
// Ajouter un parametre (encode automatiquement)
url.searchParams.set("name", "Jean-Pierre & fils");
url.toString()
// "https://api.example.com:8443/v2/users?role=admin&name=Jean-Pierre+%26+fils#top"
URLSearchParams encode automatiquement avec le format formulaire (espaces en +). C'est correct pour les query strings mais pas pour les paths. Encore une subtilite qui mord les gens en prod.
URL relatives et absolues
Une URL absolue contient le scheme et le host : https://example.com/page.
Une URL relative est résolue par rapport a une URL de base :
Base : https://example.com/blog/article-1
"/about" -> https://example.com/about
"./images/cat.png" -> https://example.com/blog/images/cat.png
"../index.html" -> https://example.com/index.html
"//cdn.example.com/lib.js" -> https://cdn.example.com/lib.js
La dernière forme (//cdn.example.com) est une URL protocol-relative. Elle hérité du scheme de la page courante. On l'utilisait beaucoup quand les sites servaient du HTTP et du HTTPS. Aujourd'hui, avec HTTPS partout, c'est moins utile mais tu la croiseras dans du code legacy.
Punycode : les domaines internationaux
Comment taper https://cafe.fr si le "e" est en fait un "e" avec accent ? Les noms de domaine ne supportent que l'ASCII. La solution s'appelle punycode.
muenchen.de -> pas de probleme, que de l'ASCII
munich.de -> pareil
cafe.fr -> si le e a un accent : xn--caf-dma.fr
Le prefixe xn-- signale un domaine encode en punycode. Le navigateur affiche la version lisible mais envoie la version punycode dans la requête HTTP.
Sur paltemps.fr, on est reste sur de l'ASCII simple pour le domaine, mais on a deja eu des surprises avec des liens contenant des caractères accentues dans le path.
Résumé
- Une URL a 7 composants : scheme, host, port, path, query, fragment
- Le fragment n'est jamais envoye au serveur
%20pour les paths,+pour les query strings de formulairesencodeURIComponentpour les valeurs,encodeURIpour les URL completes- L'API
URLen JavaScript gere l'encoding automatiquement - Les domaines internationaux passent par le punycode (
xn--)
Precedent : 00 - Introduction Suivant : 02 - La requête HTTP