Aller au contenu principal

2. Caractères (Characters)

Ce chapitre définit les jeux de caractères, les mécanismes d'encodage et les règles de traitement utilisés dans les URI.


Fondamentaux de l'encodage des caractères

La syntaxe URI fournit une méthode pour encoder des données dans une séquence de caractères, probablement dans le but d'identifier une ressource.

Hiérarchie d'encodage:

Ressource → Caractères URI → Octets → Transmission/Stockage

Jeu de caractères: Les URI sont basés sur le jeu de caractères US-ASCII, composé de chiffres, de lettres et de quelques symboles graphiques


2.1. Encodage en pourcentage (Percent-Encoding)

Objectif

Un mécanisme d'encodage en pourcentage est utilisé pour représenter un octet de données dans un composant lorsque le caractère correspondant à cet octet est en dehors de l'ensemble autorisé ou est utilisé comme délimiteur.

Format d'encodage

pct-encoded = "%" HEXDIG HEXDIG

Format: Un encodage en pourcentage consiste en un caractère pourcent "%" suivi de deux chiffres hexadécimaux représentant la valeur numérique de cet octet

Exemples

CaractèreBinaireHexadécimalEncodage en pourcentage
Espace001000000x20%20
!001000010x21%21
#001000110x23%23
é (français)-0xC3A9%C3%A9

Règles de casse

Équivalence: Les chiffres hexadécimaux majuscules 'A' à 'F' sont équivalents aux chiffres minuscules 'a' à 'f'

Normalisation: Deux URI qui ne diffèrent que par la casse des chiffres hexadécimaux utilisés dans les octets encodés en pourcentage sont équivalents

Recommandation: Les producteurs et normalisateurs d'URI devraient (SHOULD) utiliser des chiffres hexadécimaux majuscules pour tous les encodages en pourcentage

Recommandé: %2F %3A %5B
Non recommandé: %2f %3a %5b

2.2. Caractères réservés (Reserved Characters)

Définition

Les URI incluent des composants et sous-composants délimités par des caractères de l'ensemble "réservé". Ces caractères sont appelés "réservés" car ils peuvent (ou ne peuvent pas) être définis comme délimiteurs.

Ensemble de caractères réservés

reserved    = gen-delims / sub-delims

gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"

sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="

Classification

Délimiteurs généraux (gen-delims)

CaractèreObjectifExemple
:Sépare le schéma et l'autoritéhttp:
/Séparateur de chemin/path/to/resource
?Séparateur de requête?key=value
#Séparateur de fragment#section
[ ]Limites d'adresse IPv6[2001:db8::1]
@Séparateur d'informations utilisateuruser@host

Sous-délimiteurs (sub-delims)

CaractèreUtilisation courante
! $ ' ( ) *Séparation de sous-composants dans le chemin ou la requête
+Représentation alternative de l'espace
,Séparateur de liste
;Séparateur de paramètre
=Séparateur clé-valeur
&Séparateur de paramètre de requête

Règles d'encodage

Gestion des conflits: Si les données d'un composant URI entrent en conflit avec l'objectif d'un caractère réservé en tant que délimiteur, alors les données en conflit doivent (MUST) être encodées en pourcentage avant la formation de l'URI

Exemples:

Chemin contenant le caractère "?":
Original: /path/file?.txt
Encodé: /path/file%3F.txt

Requête contenant le caractère "&":
Original: ?name=Tom&Jerry
Correct: ?name=Tom%26Jerry (si & n'est pas un délimiteur)
Ou: ?name=Tom&name=Jerry (si & est un délimiteur)

Équivalence

Important: Les URI qui diffèrent dans le remplacement d'un caractère réservé par son octet encodé en pourcentage correspondant ne sont PAS équivalents

http://example.com/path?key=value
http://example.com/path%3Fkey=value

Ces deux URI ne sont PAS équivalents

2.3. Caractères non réservés (Unreserved Characters)

Définition

Les caractères autorisés dans un URI mais n'ayant pas d'objectif réservé sont appelés non réservés.

Ensemble de caractères non réservés

unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"

Comprend:

  • ALPHA: Lettres majuscules et minuscules (A-Z, a-z)
  • DIGIT: Chiffres décimaux (0-9)
  • -: Tiret
  • .: Point
  • _: Trait de soulignement
  • ~: Tilde

Règles d'encodage

Équivalence: Les URI qui diffèrent dans le remplacement d'un caractère non réservé par son octet US-ASCII encodé en pourcentage correspondant sont équivalents

Normalisation: Les octets encodés en pourcentage correspondant à des caractères non réservés devraient (SHOULD) être décodés

URI équivalents:
http://example.com/~user
http://example.com/%7Euser

Normalisé en:
http://example.com/~user

Plage d'encodage en pourcentage

Ne devrait PAS être créé (SHOULD NOT):

  • ALPHA: %41-%5A (A-Z), %61-%7A (a-z)
  • DIGIT: %30-%39 (0-9)
  • Tiret: %2D
  • Point: %2E
  • Trait de soulignement: %5F
  • Tilde: %7E

Devrait être décodé: Lorsque ces encodages sont trouvés dans un URI, les normalisateurs devraient (SHOULD) les décoder en leurs caractères non réservés correspondants


2.4. Quand encoder ou décoder (When to Encode or Decode)

Quand encoder

Producteurs d'URI:

  1. Lors de la production de l'URI, doivent (MUST) encoder en pourcentage les caractères non autorisés
  2. Les caractères réservés ne sont laissés non encodés que lorsqu'ils sont utilisés comme délimiteurs
  3. Les caractères non réservés ne devraient pas (SHOULD NOT) être encodés

Exemples:

# Encodage du chemin
path = "/files/my document.pdf"
encoded = "/files/my%20document.pdf"

# Encodage de la requête
query = "?name=John Doe&age=30"
encoded = "?name=John%20Doe&age=30"

Quand décoder

Consommateurs d'URI:

  1. Après l'analyse de l'URI, décoder les composants selon les besoins
  2. Ne pas décoder prématurément (peut changer la structure de l'URI)
  3. Décoder chaque composant une seule fois

Exemple dangereux:

Original: /path%2Fto%2Ffile
Décodage prématuré: /path/to/file (structure du chemin modifiée!)

Correct: Analyser d'abord, puis décoder chaque segment
Segment 1: "path%2Fto%2Ffile" → Décoder → "path/to/file"

Problème de double encodage

Données originales: "100%"
Premier encodage: "100%25"
Deuxième encodage erroné: "100%2525"

Lors du décodage:
"100%2525" → "100%25" → "100%"

2.5. Identification des données (Identifying Data)

Jeux de caractères et encodage

Caractère vs Octet:

  • Les URI sont des séquences de caractères
  • Les caractères sont encodés en octets pour la transmission/le stockage
  • UTF-8 est l'encodage de caractères recommandé

Identificateurs de ressources internationalisés (IRI)

Extension IRI: RFC 3987 définit les IRI, qui permettent l'utilisation de caractères Unicode

Conversion:

IRI: http://例え.jp/引き出し
↓ Encoder en UTF-8 et encoder en pourcentage
URI: http://xn--r8jz45g.jp/%E5%BC%95%E3%81%8D%E5%87%BA%E3%81%97

Meilleures pratiques

Production d'URI:

  1. Encoder les caractères non-ASCII en UTF-8
  2. Encoder en pourcentage les octets résultants
  3. Utiliser des chiffres hexadécimaux majuscules
  4. Ne pas encoder les caractères non réservés

Consommation d'URI:

  1. Analyser par composant
  2. Décoder les encodages en pourcentage
  3. Interpréter les octets en utilisant UTF-8
  4. Gérer les encodages invalides

Référence rapide des jeux de caractères

Classification complète des caractères

Caractères URI
├── Non réservés (unreserved)
│ ├── ALPHA: A-Z, a-z
│ ├── DIGIT: 0-9
│ └── Symboles: - . _ ~

├── Réservés (reserved)
│ ├── Délimiteurs généraux (gen-delims): : / ? # [ ] @
│ └── Sous-délimiteurs (sub-delims): ! $ & ' ( ) * + , ; =

└── Encodé en pourcentage (pct-encoded): %HEXDIG HEXDIG

Arbre de décision d'encodage

Le caractère doit apparaître dans l'URI?
├─ Est un caractère non réservé? → Utiliser directement
├─ Est un caractère réservé?
│ ├─ Utilisé comme délimiteur? → Utiliser directement
│ └─ Utilisé comme données? → Encoder en pourcentage
└─ Autre caractère? → Encoder en pourcentage

Table d'encodage des caractères courants

CaractèreObjectifEncodage
EspaceSéparation%20 ou + (dans la requête)
!Sous-délimiteur%21 (si encodage nécessaire)
"Guillemet%22
#Délimiteur de fragment%23 (dans les données)
$Sous-délimiteur%24 (si encodage nécessaire)
%Marqueur d'encodage%25
&Séparateur de paramètre%26 (dans les données)
'Sous-délimiteur%27 (si encodage nécessaire)
( )Sous-délimiteur%28 %29
+Espace/Sous-délimiteur%2B (dans les données)
,Séparateur de liste%2C (si encodage nécessaire)
/Séparateur de chemin%2F (dans les données)
:Séparateur de schéma%3A (dans les données)
;Séparateur de paramètre%3B (si encodage nécessaire)
=Séparateur clé-valeur%3D (si encodage nécessaire)
?Séparateur de requête%3F (dans les données)
@Séparateur d'info utilisateur%40 (dans les données)
[ ]Limites IPv6%5B %5D

Recommandations d'implémentation

Implémentation de l'encodage

def percent_encode(text, safe=''):
"""Encoder le texte en pourcentage"""
result = []
for char in text:
if char in safe or is_unreserved(char):
result.append(char)
else:
# Encoder en UTF-8 et encoder en pourcentage
for byte in char.encode('utf-8'):
result.append(f'%{byte:02X}')
return ''.join(result)

def is_unreserved(char):
"""Vérifier si le caractère est non réservé"""
return (char.isalnum() or
char in '-._~')

Implémentation du décodage

def percent_decode(text):
"""Décoder le texte en pourcentage"""
result = bytearray()
i = 0
while i < len(text):
if text[i] == '%' and i + 2 < len(text):
try:
byte = int(text[i+1:i+3], 16)
result.append(byte)
i += 3
except ValueError:
result.extend(text[i].encode('utf-8'))
i += 1
else:
result.extend(text[i].encode('utf-8'))
i += 1
return result.decode('utf-8', errors='replace')

Chapitre suivant: 3. Composants syntaxiques (Syntax Components) - Composants structurels des URI