Qu’est-ce qu’une URL d’image ?
Une URL d’image est une adresse réseau qui identifie une ressource image et peut inclure des paramètres de transformation ou de diffusion. Elle peut désigner un fichier fixe ou un service qui génère une réponse à partir du chemin ou des paramètres de requête demandés.
Fonctionnement des URL d’image
Une URL d’image remplit deux fonctions : elle désigne une ressource et constitue la partie principale de la clé sous laquelle les navigateurs et les CDN stockent la réponse. Un chemin fixe peut correspondre à des octets stockés. Un service de transformation analyse au contraire l’URL pour en tirer une recette : imgproxy, par exemple, lit les options de traitement et l’adresse source dans les segments du chemin, et le format de sortie dans l’extension, tandis que d’autres services extraient une taille ou un format des paramètres de requête. Le client récupère le contenu de l’URL, le serveur peut choisir parmi plusieurs représentations à l’aide d’en-têtes de requête tels que Accept, et chaque cache stocke le résultat sous une clé comprenant l’URL et tous les autres éléments qu’il est configuré pour y inclure, comme les en-têtes de requête que la réponse mentionne dans Vary. Deux URL qui ne diffèrent que par un détail ignoré par le service restent stockées séparément par tout cache qui conserve ce détail dans sa clé.
Points clés
- L’extension du fichier détermine-t-elle le format de l’image ? Non. Un service peut interpréter l’extension comme le format de sortie demandé, comme le fait imgproxy, mais c’est la réponse qui détermine le format : le serveur le déclare dans
Content-Type, et, pour un élémentimg, la norme HTML indique que les navigateurs devraient également examiner les premiers octets de l’image pour en détecter le format, l’en-tête donnant le type officiel. Une URL se terminant par.jpgpeut donc fournir du WebP ou de l’AVIF, et l’image peut tout de même s’afficher. Lorsque le serveur choisit ce format à partir de l’en-tête de requêteAccept, une même URL a plusieurs réponses : le serveur devrait envoyerVary: Accept, et chaque CDN ou proxy de cache placé en amont doit tenir compte deAccept, faute de quoi un cache peut réutiliser une image WebP ou AVIF stockée pour un navigateur qui ne l’a pas demandée. L’extension compte néanmoins pour certains intermédiaires : le CDN de Cloudflare décide de ce qu’il met en cache par défaut selon l’extension du fichier et non selon le type MIME. Une URL d’image sans extension répertoriée n’est donc pas mise en cache par défaut, sauf si une règle de cache le prévoit. - Deux URL contenant les mêmes paramètres dans un ordre différent sont-elles identiques pour un cache ? Uniquement si le cache normalise la chaîne de requête ou l’exclut de sa clé. La RFC 3986 compare les URI comme des chaînes de caractères, et ses règles de normalisation ne réordonnent pas les paramètres de requête. Amazon CloudFront précise que, lorsque sa mise en cache repose sur les paramètres de la chaîne de requête,
?color=red&size=largeet?size=large&color=redsont mis en cache comme deux objets distincts et que la casse des noms et des valeurs des paramètres compte également. Cloudflare inclut la chaîne de requête complète dans sa clé de cache par défaut et propose les options « Sort query string » et « Ignore query string ». Générer les paramètres selon un ordre et une casse fixes évite les entrées de cache et les transformations en double. L’inverse compte aussi : un paramètre qui modifie l’image doit faire partie de la clé de cache, car un cache configuré pour ignorer la chaîne de requête attribue la même clé aux URL qui ne diffèrent que par leurs paramètres. - N’importe qui peut-il modifier les paramètres d’une URL de transformation ? Oui, sauf si le service refuse les requêtes sans signature valide ou restreint autrement ce qu’il accepte. Générer des URL signées ne suffit pas si le service continue de servir les URL non signées : imgproxy laisse la vérification des signatures désactivée par défaut et recommande de l’activer en production afin qu’un attaquant ne puisse pas mener une attaque par déni de service en demandant de nombreux redimensionnements différents ; sa signature est un HMAC calculé sur le chemin de l’URL. Une signature ne couvre que l’URL : imgproxy précise que les en-têtes de requête ne peuvent pas être signés, ce qui compte lorsque le format de sortie ou la largeur provient d’un en-tête.
- Pourquoi une page peut-elle afficher une image provenant d’une autre origine sans pouvoir lire ses pixels ? Une page peut normalement afficher une image interorigines, mais la dessiner dans un canvas sans autorisation CORS contamine ce canvas. Dès lors,
getImageData(),toBlob()ettoDataURL()lèvent une exceptionSecurityError; cela empêche une page d’utiliser des images pour extraire des données privées d’autres sites. Pour lire les pixels, l’hôte de l’image doit envoyer un en-têteAccess-Control-Allow-Originqui autorise la page, et l’élémentimgdoit comporter l’attributcrossorigin(défini aveccrossOriginlorsqu’un script crée l’image). Aveccrossorigin, le navigateur envoie un en-tête de requêteOrigin, absent d’une simple requête interoriginesimg. Cloudflare inclut l’en-têteOriginde la requête dans sa clé de cache par défaut ; les requêtes visant une même URL mais dont cet en-tête diffère y sont donc mises en cache séparément.
Quand les URL d’image sont importantes
La forme d’une URL d’image devient importante lorsque l’image est transformée à la demande ou diffusée par un CDN, car l’URL détermine alors à la fois les octets produits et la copie en cache réutilisée. Avant de publier les URL, fixez l’ordre et la casse des paramètres, déterminez si le format de sortie est indiqué dans l’URL ou négocié selon l’en-tête Accept (la négociation n’est sûre que si chaque cache placé devant le service distingue les formats), et décidez si l’URL est signée. Les pages et les autres systèmes qui ont enregistré une URL continuent de demander exactement cette forme.
Comment Transloadit facilite l’utilisation des URL d’image
Une URL d’image du Smart CDN de Transloadit est une URL de transformation de ce type. Le nom du Workspace est le sous-domaine de tlcdn.com, le chemin contient le nom du Template et le chemin du fichier source, et les paramètres de requête tels que w=730 sont transmis au Template sous forme d’Assembly Variables telles que ${fields.w}. C’est donc le Template qui détermine quels paramètres ont un effet. L’URL peut être signée avec une date d’expiration (exp) et une signature (sig) ; la signature doit être générée sur votre back-end, car elle utilise l’Auth Secret. Si une URL signée ou ses paramètres sont modifiés ensuite, la signature ne correspond plus. Cela empêche les tiers de modifier l’URL ou ses paramètres uniquement si les requêtes non signées sont refusées. Or, les pages liées ne décrivent pas le traitement d’une requête non signée visant le même Template ; testez donc ce comportement sur votre propre Workspace avant de vous fier à la signature.
La procédure de signature trie les paramètres de requête avant le calcul de la signature. Les pages liées ne précisent pas si deux URL dont les paramètres ne diffèrent que par leur ordre partagent un même résultat en cache ; générez donc les paramètres dans un ordre fixe.
Références
- RFC 3986 : syntaxe générique des URI, section 6 (normalisation et comparaison)
- RFC 9110 : sémantique HTTP, sections 8.3 (Content-Type) et 12.5.5 (Vary)
- RFC 9111 : mise en cache HTTP, sections 2 et 4.1 (clés de cache et Vary)
- Standard HTML : images, y compris les règles de détection du type d’image
- Standard de détection des types MIME du WHATWG : détection dans un contexte d’image
- Standard HTML : l’élément canvas et l’indicateur origin-clean
- MDN : utiliser des images interorigines dans un canvas
- MDN : l’attribut crossorigin
- MDN : l’en-tête de requête Origin
- Amazon CloudFront : mettre du contenu en cache selon les paramètres de la chaîne de requête
- Cloudflare : clés de cache
- Cloudflare : comportement du cache par défaut et extensions de fichiers mises en cache par défaut
- imgproxy : format des URL de traitement
- imgproxy : signer une URL
- imgproxy : options de configuration, détection du format et mise en cache