14 octobre 2009

Choisir un vocabulaire XML pour représenter des entêtes HTTP

XML est un outil puissant pour toutes personnes cherchant à structurer de l'information. On peut facilement et rapidement baliser tout et n'importe quoi.
Cet outil serait magique si cette apparente simplicité ne cachait une joyeuse anarchie pouvant engendrer quelques maux de tête...

Données brutes

Admettons que l'on souhaite formaliser en XML les entêtes d'une réponse à une requête HTTP. Voici un extrait :

Date: Wed, 14 Oct 2009 13:52:20 GMT
Expires: Thu, 01 Jan 1970 00:20:55 GMT
Last-Modified: Thu, 01 Jan 1970 00:20:55 GMT
Content-Length: 43
Content-Type: text/html; charset=utf-8
Connection: keep-alive

Données xmlisées - première tentative

Avec XML pas de problème et très rapidement on peut obtenir ça:

<headers>
    <header name="Date" content="Wed, 14 Oct 2009 13:52:20 GMT" />
    <header name="Expires" content="Thu, 01 Jan 1970 00:20:55 GMT" />
    <header name="Last-Modified" content="Thu, 01 Jan 1970 00:20:55 GMT" />
    <header name="Content-Length" content="43" />
    <header name="Content-Type" content="text/html; charset=utf-8" />
    <header name="Connection" content="keep-alive" />
</headers>

Données xmlisées - deuxième tentative

Cependant, si on s'était levé du pied gauche, on aurait pu également écrire :
<http>
    <name>Date</name>
    <value>Wed, 14 Oct 2009 13:52:20 GMT</value>
    <name>Expires</name>
    <value>Thu, 01 Jan 1970 00:20:55 GMT</value>
    <name>Last-Modified</name>
    <value>Thu, 01 Jan 1970 00:20:55 GMT</value>
    <name>Content-Length</name>
    <value>43</value>
    <name>Content-Type</name>
    <value>text/html; charset=utf-8</value>
    <name>Connection</name>
    <value>keep-alive</value>
</http>

Vocabulaires adhoc

Les 2 exemples précédents sont des vocabulaires adhoc. Ils sont totalement valides syntaxiquement et parfaitement utilisables. Par contre, si l'on choisit la deuxième version, on risque vite de se rendre compte à l'usage que l'on aurait du probablement choisir une autre structuration...

Et voilà tout le problème d'XML, il est si facile à utiliser qu'on en oublie vite qui faut réfléchir un petit peu si on veut éviter de galérer par la suite !

Bien sur, toutes personnes confrontées à cette problématique peut passer quelques heures pour faire une analyse du problème et aboutir à une grammaire de description des entêtes HTTP tout à fait pratique et pérenne. Mais avant de faire chauffer son cerveau une petite séance de Google n'a jamais fait de mal à personne.

Vocabulaire standards

Trouver un vocabulaire XML (sous forme ou non de XML Schéma ou de Relax NG) n'est pas une chose aisée. Mais à l'exception de quelques domaines, on arrive toujours à trouver quelques choses. Pour notre exemple, on peut utiliser tout ou en partie au moins deux normes.

HTTP Vocabulary in RDF

Pour tout ce qui touche au Web, le W3C a une solution ! Et notre petit exemple n'échappe pas à la règle, il existe donc un vocabulaire normalisé pour les requêtes HTTP :

<http:headers rdf:parseType="Collection">
 <http:MessageHeader>
  <http:fieldName>Date</http:fieldName>
  <http:headerName rdf:resource="http://www.w3.org/2008/http-header#date"/>
  <http:fieldValue>Wed, 14 Oct 2009 13:52:20 GMT</http:fieldValue>
 </http:MessageHeader>
 <http:MessageHeader>
  <http:fieldName>Expires</http:fieldName>
  <http:headerName rdf:resource="http://www.w3.org/2008/http-header#expires"/>
  <http:fieldValue>Thu, 01 Jan 1970 00:20:55 GMT</http:fieldValue>
 </http:MessageHeader>
 <http:MessageHeader>
  <http:fieldName>Last-Modified</http:fieldName>
  <http:headerName rdf:resource="http://www.w3.org/2008/http-header#last-modified"/>
  <http:fieldValue>Thu, 01 Jan 1970 00:20:55 GMT</http:fieldValue>
 </http:MessageHeader>
 <http:MessageHeader>
  <http:fieldName>Content-Length</http:fieldName>
  <http:headerName rdf:resource="http://www.w3.org/2008/http-header#content-length"/>
  <http:fieldValue>43</http:fieldValue>
 </http:MessageHeader>
 <http:MessageHeader>
  <http:fieldName>Content-Type</http:fieldName>
  <http:headerName rdf:resource="http://www.w3.org/2008/http-header#content-type"/>@@@TBD@@@
  <http:fieldValue>text/html; charset=utf-8</http:fieldValue>
  <http:headerElements rdf:parseType="Collection">
   <http:HeaderElement>
    <http:elementName>text/html</http:elementName>
    <http:params rdf:parseType="Collection">
     <http:Param>
      <http:paramName>charset</http:paramName>
      <http:paramValue>utf-8</http:paramValue>
     </http:Param>
    </http:params>
   </http:HeaderElement>
  </http:headerElements>
 </http:MessageHeader>
 <http:MessageHeader>
  <http:fieldName>Connection</http:fieldName>
  <http:headerName rdf:resource="http://www.w3.org/2008/http-header#connection"/>
  <http:fieldValue>keep-alive</http:fieldValue>
 </http:MessageHeader>
</http:headers>

On remarque que le W3C prévoit la décomposition des valeurs multiples.

XMPP Extensions

On pourrait se contenter de la proposition du W3C, mais il en existe au moins une autre solution se présentant sous la forme d'une extension pour le protocole XMPP : XEP-0131: Stanza Headers and Internet Metadata

<headers xmlns='http://jabber.org/protocol/shim'>
 <header name='Date'>Wed, 14 Oct 2009 13:52:20 GMT</header>
 <header name='Expires'>Thu, 01 Jan 1970 00:20:55 GMT</header>
 <header name='Last-Modified'>Thu, 01 Jan 1970 00:20:55 GMT</header>
 <header name='Content-Length'>43</header>
 <header name='Content-Type'>text/html; charset=utf-8</header>
 <header name='Connection'>keep-alive</header>
</headers>

Conclusion

Les différentes structures présentées précédemment diffèrent légèrement les unes des autres. D'expérience cette différence s'accentuera avec la complexité des données à structurer, et plus on risque de faire des choix qui s'avèreront être mauvais à l'usage. Donc avant de partir dans la création d'un nouveau vocabulaire XML complexe, il est conseiller de faire une petite étude bibliographiques ou webographiques... cqfd.