ici & ailleurs

REST avec XMLHttpRequest

Ces derniers temps j'ai du développer un service REST et ensuite, dialoguer avec par divers moyens. J'en suis venu à me poser la question des possibilités et limites d'usage d'un tel service avec JavaScript.

Cette mini étude a pour but de déterminer si nous pouvons utiliser un service collant le plus possible aux principes REST avec Javascript et XMLHttpRequest. Il n'est donc pas question de définir ce qui fait ou non un service REST. Seuls deux points particuliers nous intéressent :

Pour réaliser les tests, j'ai écrit une petite application qui retourne les en-têtes HTTP reçus ainsi que les informations passées dans le corps ou en query string. C'est une sorte de echo amélioré. La partie cliente se contentait, elle, de retourner les en-têtes et résultats reçus.

Tous les tests ont été effectués sur le même site. Il n'y a pas eu d'accès à un autre hôte, ces problématiques étant encore très mal gérées par les navigateurs (même par ceux qui clament pouvoir le faire).

Enfin, ces tests ont été réalisés avec jQuery qui a fait un bon travail pour harmoniser les résultats. Si vous utilisez une autre librairie, ou pas de librairie du tout, vous pouvez avoir des résultats différents. Par exemple Internet Explorer comprend une réponse 204 comme 1223.

Généralités

Contrairement à pas mal de légendes circulant ici et là, vous pouvez parfaitement utiliser les 4 méthodes les plus courantes avec XMLHttpRequest (GET, POST, PUT, DELETE).

Les tests démontrent que toutes les réponses de type 200 sont très bien gérées par tous les navigateurs et sans surprise.

Les réponses en erreur (type 400 ou 500) passent sans problème sauf avec Opera si la réponse n'a pas de contenu. Il est donc nécessaire de toujours envoyer un contenu à ce type de réponse. Le problème ne se pose pas avec d'autres type de réponse (204 par exemple).

Les réponses de type 300 (redirection) sont les plus problématiques. Par défaut, le navigateur va suivre la redirection et ce comportement ne peut pas être modifié. Plus gênant, vous ne savez pas où vous êtes partis. La solution peut être d'ajouter un en-tête Content-Location sur certaines de vos ressources.

En soit, le comportement des redirections ne semble pas un problème, vous obtenez ce que vous vouliez. Sauf avec Firefox. Celui-ci ne transmet pas les en-têtes que vous avez pu ajouter sur votre requête d'origine. C'est très problématique si votre service sert des contenus différents en fonction de l'en-tête Accept.

Enfin, dans une tradition de n'importe quoi, Internet Explorer juge bon, dans certains cas, de suivre automatiquement les redirections avec la même méthode.

On notera également, que la présence d'un en-tête Location sur une réponse autre que de type 300 n'entraîne heureusement pas de redirection automatique.

Dans l'ensemble, les résultats sont moins dramatiques que ce à quoi je m'attendais. Ils valident même l'utilisation d'un service utilisant pleinement HTTP sans avoir de problème majeur.

Les résultats

Méthode Status FF 3.5 FF 4.0 Safari 5.0 Opera 11.0 IE 6.0 SP2 IE 7.0 IE 8.0
GET 200 ok ok ok ok ok ok ok
POST 200 ok ok ok ok ok ok ok
PUT 200 ok ok ok ok ok ok ok
DELETE 200 ok ok ok ok ok ok ok
POST 201 ok ok ok ok ok ok ok
PUT 201 ok ok ok ok ok ok ok
POST 202 ok ok ok ok ok ok ok
PUT 202 ok ok ok ok ok ok ok
POST 203 ok ok ok ok ok ok ok
PUT 203 ok ok ok ok ok ok ok
POST 204 ok ok ok ok ok ok ok
PUT 204 ok ok ok ok ok ok ok
DELETE 204 ok ok ok ok ok ok ok
 
GET 400 ok ok ok (2) ok ok ok
POST 400 ok ok ok (2) ok ok ok
PUT 400 ok ok ok (2) ok ok ok
DELETE 400 ok ok ok (2) ok ok ok
GET 403 ok ok ok (2) ok ok ok
POST 403 ok ok ok (2) ok ok ok
PUT 403 ok ok ok (2) ok ok ok
DELETE 403 ok ok ok (2) ok ok ok
GET 404 ok ok ok (2) ok ok ok
POST 404 ok ok ok (2) ok ok ok
PUT 404 ok ok ok (2) ok ok ok
DELETE 404 ok ok ok (2) ok ok ok
GET 405 ok ok ok (2) ok ok ok
POST 405 ok ok ok (2) ok ok ok
PUT 405 ok ok ok (2) ok ok ok
DELETE 405 ok ok ok (2) ok ok ok
GET 406 ok ok ok (2) ok ok ok
POST 406 ok ok ok (2) ok ok ok
PUT 406 ok ok ok (2) ok ok ok
DELETE 406 ok ok ok (2) ok ok ok
GET 409 ok ok ok (2) ok ok ok
POST 409 ok ok ok (2) ok ok ok
PUT 409 ok ok ok (2) ok ok ok
DELETE 409 ok ok ok (2) ok ok ok
 
GET 500 ok ok ok (2) ok ok ok
POST 500 ok ok ok (2) ok ok ok
PUT 500 ok ok ok (2) ok ok ok
DELETE 500 ok ok ok (2) ok ok ok
GET 503 ok ok ok (2) ok ok ok
POST 503 ok ok ok (2) ok ok ok
PUT 503 ok ok ok (2) ok ok ok
DELETE 503 ok ok ok (2) ok ok ok
 
GET 301 (1) (1) ok ok ok ok ok
POST 301 (1) (1) ok ok ok ok ok
PUT 301 (1) (1) ok ok (3) (3) (3)
DELETE 301 (1) (1) ok ok (3) (3) (3)
GET 302 (1) (1) ok ok ok ok ok
POST 302 (1) (1) ok ok ok ok ok
PUT 302 (1) (1) ok ok (3) (3) (3)
DELETE 302 (1) (1) ok ok (3) (3) (3)
GET 303 (1) (1) ok ok ok ok ok
POST 303 (1) (1) ok ok ok ok ok
PUT 303 (1) (1) ok ok ok ok ok
DELETE 303 (1) (1) ok ok ok ok ok