Une requête HTTP est une demande envoyée au serveur par le navigateur. Cela peut être une demande d'un contenu d'un fichier : page html, fichier quelconque... Mais cela peut ne pas aboutir à un retour de contenu. Il est simplement envoyé une commande au serveur.
Dans tout les cas, le navigateur récuperera un code de retour (les codes comme 404, 202 etc...)
En schématisant, une requête HTTP contient deux parties :
L'entête contient entre autre :
Le corps de la requête contient des informations additionnelles. Leurs présences et leurs contenus dépendent du type de la requête.
La méthode GET est simple : on appelle juste une URL classique. Celle-ci peut contenir des paramètres, que le serveur/la page interprétera.
Exemple : http://monsite.com/page.php?param1=valeur1¶m2=valeur2...
Les paramètres sont séparés par une perluette & et chacun est composé comme suit : nom_du_parametre=valeur_du_parametre.
En PHP, dans la page correspondante à l'url, on pourra récupérer ces informations dans le tableau global prédéfini $_GET.
En méthode POST, nous avons également des paramètres. Par contre, ceux-ci ne sont plus indiqués dans l'url, mais dans le corps de la requête. La façon dont ils sont stockés est la même que pour GET, c'est à dire nom_du_parametre=valeur_du_parametre et chacun d'eux séparé par une perluette.
Il faut spécifier également dans l'entête que le type du contenu est application/x-www-form-urlencoded.
En PHP, on pourra récupérer les paramètres dans le tableau $_POST.
L'envois de fichiers fonctionne aussi avec la méthode POST mais necessite plusieurs arguments : # Le Content-Type qui doit être à "multipart/form-data" suivit d'une suite de charactères de délimitation. En effet, ce content-type signifie qu'il va y avoir plusieurs parties dans la corps de la requête et cette chaine permettra donc de les délimiter. Ce qui donnera au final le résultat suivant :Content-Type: multipart/form-data, boundary=3894641383813313890". A priori, on peut mettre n'importe quoi comme delimitateur (à confirmer) # Chaque partie est ensuite préfixée par une entête "Content-Disposition : form-data" et est séparée par "--delimiteur"
Plutôt que de continuer dans la théorie, je pense qu'un exemple sera plus parlant. Imaginons le formulaire html suivant :
<form enctype="multipart/form-data" action="page.php" method="post">
<input type="hidden" name="addfile" value="1">
<input type="file" name="filename"/>
<input type="submit" value="Add"/>
</form>
Il s'agit d'un simle formulaire d'upload de fichier avec un parametre de type "hidden" en plus (addfile=1). Le corp de la requête HTTP sera le suivant: %%
content-Type: multipart/form-data, boundary=111222111\r\n
\r\n
Content-disposition: form-data;name="addfile"\r\n
\r\n
1\r\n
Content-disposition: form-data;name="filename";filename="nom_fichier"\r\n
Content-Type: application/octet-stream\r\n
Content-Length: taille_du_fichier\r\n
\r\n
...Contenu du fichier...
Quelques petites remarques :
Pour plus d'information sur l'upload de fichier en HTTP, voir le RFC 1867 : http://www.faqs.org/rfcs/rfc1867.html
Dans Mozilla, il existe un objet XMLHttpRequest qui permet, comme son nom l'indique, de faire des requetes HTTP avec un serveur WEB. Nous alons voir comment une application XUL permet, en quelque sorte, d'émuler des liens et des formulaires html.
Attention, ce type de requête demande certaines permissions et échoura si vous inserez ce code dans un fichier XUL et que vous le lancez tel quel (mais fonctionnera sans problème si l'application est dans un paquage XPI). Pour pouvoir passez outre, vous devez ajouter la (les) ligne(s) suivante(s) :
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
Pour pouvoir utiliser l'opbjet XMLHTTPRequest.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
Pour pouvoir utiliser les objets XPCOM (seulement nécessaire pour l'envoi de fichier)
Cela fera apparaitre un dialogue de Mozilla vous demandant si vous permettez à ce script d'avoir les permission UniversalBrowserRead ou UniversalXPConnect. Voir http://books.mozdev.org/html/mozilla-chp(..) pour plus de renseignements sur les permissions de mozilla.
Il s'agit du type de requête le plus facile à faire. Si vous connaissez un petit peu le PHP (ou d'autre langage du même type genre JSP), vous savez sans doute passer des parametres d'une page à l'autre en utilisant page.php?nom1=val1&nom2=val2 etc .... Le principe en XUL (enfin plutôt en Javascript puisqu'il s'agit de coder dans ce langage) est exactement le même.
Le code nécessaire est donc le suivant :
var requete=new String("http://monsite.com/page.php?nom1=val1&nom2=val2");
var xmlr = new XMLHttpRequest();
xmlr.open("GET",requete,false);
xmlr.send(null);
La méthode open() possède 5 paramètres :
;method:Le type de méthode HTTP à utiliser (GET ou POST) ;url: L'URL de destination (avec les paramètres GET) ;async: Si false, la méthode est bloquante send est bloquante et attendra la fin de la réponse du serveur. Dans le cas contraire, la méthode send retourne tout de suite et s'execute en tache de fond ;login:Le login si nécessaire (pour quel type d'authentification ?) ;password:Le mot de passe associé au loginLa méthode send prend en paramètre le corp de la requete qui est inutile de renseigner dans le cas d'une requete GET.
La méthode POST est un peu plus complexe et l'exemple qui suit permet d'émuler un formulaire html au moyen de l'objet XMLHttpRequest.
Soit le formulaire html suivant :
<form action="page.php" method="post">
<input type="hidden" name="createdir" value="1">
<input type="text" name="dirname"/>
<input type="submit" value="Create"/>
</form>
Ce formulaire possède 2 paramètres qu'il va falloir envoyer dans le corp de la requête HTTP
var requ=new String("createdir=1&dirname=valeur_du_champ");
var xmlr = new XMLHttpRequest();
xmlr.open("POST",
"http://monsite.com?page.php
false)
xmlr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xmlr.send(requ);
Les paramètres sont encodés de la même façon que pour la méthode GET, c'est à dire nom1=val1&nom2=val2 etc ....
Il est important de spécifier le Content-Type:application/x-www-form-urlencoded pour que le serveur web sache de quoi il s'agit.
Les paramètres seront donc disponible dans le tableau $_POST de PHP ou son équivalent dans d'autre langage.
Là ça devient du sport et il est important de bien respecter le protocole HTTP. Dans l'exemple qui suit, nous allons émuler le formulaire suivant :
<form enctype="multipart/form-data" action="page.php" method="post">
<input type="hidden" name="addfile" value="1">
<input type="file" name="filename"/>
<input type="submit" value="Add"/>
</form>
Ce formulaire est composé d'un champ d'upload de fichier et d'un paramètre de type hidden. Reportez vous au chapitre précédant pour connaitre la requète exacte que l'on va devoir envoyer.
Je n'ai pas détailler la méthode send mais sachez que celle-ci accepte plusieurs type de paramètres :
Le but du jeux va donc d'être de créer notre requête en mettant tout dans un InpoutStream.
Je part du principe que vous savez créer des objets XPCOM en javascript et que vous avez déja un objet de type 'File'. Une façon simple d'en obtenir un est d'utiliser l'objet FilePicker (boite de dialogue de séléction de fichier).
const BOUNDARY="111222111"; //ce qui va nous servir de délimiteur
const MULTI="@mozilla.org/io/multiplex-input-stream;1";
const FINPUT = "@mozilla.org/network/file-input-stream;1";
const STRINGIS="@mozilla.org/io/string-input-stream;1";
const BUFFERED="@mozilla.org/network/buffered-input-stream;1";
const nsIMultiplexInputStream=Components.interfaces.nsIMultiplexInputStream;
const nsIFileInputStream=Components.interfaces.nsIFileInputStream;
const nsIStringInputStream=Components.interfaces.nsIStringInputStream;
const nsIBufferedInputStream = Components.interfaces.nsIBufferedInputStream;
// 1
var mis=Components.classes[MULTI].createInstance(nsIMultiplexInputStream);
//2
var fin=Components.classes[FINPUT].createInstance(nsIFileInputStream);
fin.init(fic,0x01,0444,tmp); //fic est un objet de type fichier
var buf=Components.classes[BUFFERED].createInstance(nsIBufferedInputStream);
buf.init(fin,4096);
//3
var hsis=Components.classes[STRINGIS].createInstance(nsIStringInputStream);
var sheader=new String();
sheader+="\r\n";
sheader+="--"+BOUNDARY+"\r\nContent-disposition: form-data;name=\"addfile\"\r\n\r\n1";
sheader+=\r\n"+"--"+BOUNDARY+"\r\n"
sheader+="Content-disposition: form-data;name=\"filename\";filename=\""+fic.leafName+"\"\r\n";
sheader+="Content-Type: application/octet-stream\r\n";
sheader+="Content-Length: "+fp.file.fileSize+"\r\n\r\n";
hsis.setData(sheader,sheader.length);
//4
var endsis=Components.classes[STRINGIS].createInstance(nsIStringInputStream);
var bs=new String("\r\n--"+BOUNDARY+"--\r\n");
endsis.setData(bs,bs.length);
//5
mis.appendStream(hsis);
mis.appendStream(buf);
mis.appendStream(endsis);
//6
var xmlr = new XMLHttpRequest();
xmlr.open("POST","http://monsite.com/page.php",false);
xmlr.setRequestHeader("Content-Length",(mis.available()-2));
//Je ne sais pas pouquoi -2, je doit faire une erreur quelque part
xmlr.setRequestHeader("Content-Type","multipart/form-data, boundary="+BOUNDARY);
//7 :)
//8
xmlr.send(mis);
En théorie (et en pratique chez moi), cela devrai fonctionner et le fichier devrai être envoyé.
Copyright © 2003-2013 association xulfr, 2013-2016 Laurent Jouanneau - Informations légales.
Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™
sont des marques de la fondation Mozilla.