Formulaires, méthodes GET et POST

Généralités

Une autre particularité d'un site web interactif est de pouvoir récupérer et prendre en compte des données saisies par l'utilisateur et des choix (autres que celui d'afficher une page web particulière) effectués par celui-ci.

Les formulaire HTML mettent à la disposition de l'utilisateur :

Le but de cette page n'est pas de présenter la syntaxe détaillée de tout ce qu'on peut mettre dans un champ de formulaire, mais un rappel rapide de l'ensemble des possibilités est toujours utile.

Dans le programme d'exemple fourni, on remplira 2 zones de texte et, après avoir cliqué sur un bouton, une nouvelle page s'affichera avec les données qu'on a saisi.

Il existe deux méthodes de communication entre le navigateur web et le serveur pour transmettre les données des formulaires : les méthodes GET et POST.

Le programme fourni permet d'utiliser les deux méthodes de communication.

Ce qui fait le site web

Ce site web commence par demander à l'utilisateur de saisir de 2 informations :

Salut toi


Comment t'appelles-tu ?
et tu es dans quelle classe ?


Après avoir cliqué sur la bouton Répondre, l'utilisateur obtient une réponse qui tient compte des données qu'il a saisies.

Elle est de la forme :

Bonjour ... de ...

Si l'utilisateur a rempli les deux champs, ce qu'il a introduit apparaît à la place des pointillés.
Dans le cas contraire, le programme Arduino se débrouille pour donner quand même une réponse cohérente.

En dessous de cette réponse, l'utilisateur dispose de 2 liens pour demander de recommencer soit avec la même méthode de communication, soit avec l'autre.

Fonctionnement du programme Arduino

Pour téléverser le programme sur la carte Arduino, il faut d'abord mettre dans un répertoire les 3 fichiers suivants :
Sur la carte SD, on mettra les fichiers :
On supposera que l'adresse MAC et l'adresse IP de la carte Ethernet ont été configurées conformément à ce qui est dit dans la page Généralités

Avant d'examiner la fonction loop (), intéressons-nous à 2 déclarations de variables au début du programme :

La variable url est déjà connue. Elle n'était pas utilisée pour le compteur de passage qui affiche toujours la même page, mais elle a servi dans les différentes versions du site statique pour récupérer le nom du fichier HTML à afficher.

Dans le cas du site statique, on avait besoin de 14 caractères, soit la longueur maximale d'un nom de fichier MS-DOS + 2.

A présent, la variable url va contenir aussi les paramètres passés avec la méthode GET. Il faut donc prévoir davantage de caractères.

Plus précisément, l'envoi par le navigateur des valeurs d'un formulaire avec la méthode GET se fait en demandant un URL rallongé de la forme :
    adresse_ip/fichier_php?variable1=valeur1&variable2=valeur2....
avec une liste de variables et de valeurs plus ou moins longue.

Le nom des variables n'est pas du au hasard, il correspond aux noms choisis dans le formulaire HTML :



Dans le cas de notre programme, on a 2 variables :
    <input type="text" name="nom" maxlength="20" ...>
    ...
    <input type="text" name="classe" maxlength="20" ...>
Si l'envoi du formulaire se fait avec la méthode GET, ce qui est précisé un peu avant avec le nom de la page de réponse à afficher :
    <form action=repget.ahp method=get>
l'URL demandée sera de la forme :
    adresse_ip/repget.ahp?nom=...&classe=...
avec les données saisies par l'utilisateur à la place des pointillés.

Pour qu'une partie des données saisies par l'utilisateur ne soit pas perdue, il faut que la variable url ait au moins le nombre de caractères qu'il y a à partir du / jusqu'à la fin de l'URL.

Une autre variable a été déclarée pour ce programme :
    // Paramètres POST
    char post [50];
Si l'envoi du formulaire se fait avec la méthode POST, les valeurs envoyées sont stockées dans cette variable. Sa taille doit être au moins le nombre de caractères qu'il y aurait à partir du ? jusqu'à la fin de l'URL.


Intéressons-nous maintenant à ce que fait la fonction loop ()



Lorsque la carte Arduino détecte une demande de page, comme pour tous les autres programmes, la fonction lire_trame_client (...) est appelée.

Mais cette fois-ci, elle l'est avec 5 paramètres :
    lire_trame_client (client, url, sizeof (url), post, sizeof (post));
Ces paramètres sont :
  1. Identifiant du client web.
  2. Nom de la variable qui contiendra le nom de la page demandée par le navigateur et les paramètres transmis par la méthode GET.
  3. Taille de la variable précédente.
  4. Nom de la variable qui contiendra les paramètres transmis par la méthode POST.
  5. Taille de la variable précédente.
Remarque : Cette manière d'appeler lire_trame_client (...) permet dans le même programme de traiter des valeurs passées par la méthode GET et des valeurs passées par la méthode POST.

Toutefois, si le site web n'utilise que la méthode GET, on pourra se contenter d'appeler la fonction lire_trame_client (...) avec seulement 3 paramètres et un nombre de caractères suffisant pour la variable url.

Au contraire, si le site web n'utilise que la méthode POST, il faudra appeler la fonction lire_trame_client (...) avec ses 5 paramètres, mais 14 caractères suffiront pour la variable url.

Normalement, on a récupéré de nom de la page demandée par le navigateur. Mais, il se peut qu'elle n'ait pas été indiquée, si par exemple on a tapé seulement l'adresse IP de la carte Arduino.

Dans ce cas, on choisit d'appeler la page de saisie du formulaire par la méthode GET :
    // si aucun nom de fichier ne figure dans l'url
    if (! url [1])
        // mettre le nom du fichier d'accueil
        strcpy (url, "get.htm");
En supposant que l'ouverture du fichier contenant la page à afficher se passe bien, 2 cas se présentent :
Mais peut-être n'avez-vous jamais entendu parler de fichier AHP ?
C'est tout à fait normal.

La saisie d'un formulaire peut se faire avec un fichier HTML classique (s'il n'y a pas de contrôle d'erreur). Par contre, le traitement des données saisies, se fait, sur un serveur web classique, au moyen d'un fichier PHP.

L'une des significations du sigle PHP est "PHP Hypertext Protocol".

Mais comme ça a été précisé, la carte Arduino a trop peu de mémoire pour posséder un vrai interpréteur PHP.

J'ai donc décidé que lorsque des données saisies par l'utilisateur sont traitées par le serveur, le fichier correspondant à la page web après ce traitement seraient des fichiers AHP (suffixe .ahp) abréviation de "Arduino Hypertext Protocol".

Il y a quand me une grosse différence avec un fichier PHP. Un vrai fichier PHP (je sais qu'il y en a qui mélangent du HTML et du code PHP dans le même fichier, ce que je désapprouve) c'est un programme. Ce programme pourra éventuellement utiliser un ou plusieurs squelettes de fichier HTML.

Un fichier AHP, c'est un squelette de fichier HTML et la partie programme est intégrée au serveur Arduino.

Cette manière de procéder a ses limites : autant un site web peut utiliser des dizaines ou centaines de fichiers PHP (chacun faisant un travail différent), autant le programme Arduino qui permettrait la même chose serait très long, et peut être qu'on manquerait de mémoire.

Mais pour un petit nombre de traitements simples, pas de problème.

On commence donc par tester si on a affaire à un fichier AHP. Ça pourrait se faire en testant les 4 derniers caractères (suffixe) du fichier sélectionné. Toutefois, comme les fichiers AHP de ce programme ont pour nom repget.ahp et reppost.ahp, le test est fait sur les 3 lettres du début :
    // si page de réponse à un formulaire
    if (memcmp (url, "rep", 3) == 0)
    {
Si c'est bien l'un des deux fichiers AHP, on commence par récupérer les valeurs des variables. Selon le fichier AHP, ça se fait par la méthode GET ou la méthode POST.
    // si réponse à un formulaire par la méthode get
    if (memcmp (url,"repget", 6) == 0)
    {
        // récupérer les valeurs des variables
        lecvar_get ("nom", url, valnom);
        lecvar_get ("classe", url, valclasse);
    }
    // sinon méthode post
    else
    {
        // récupérer les valeurs des variables
        lecvar_post ("nom", post, valnom);
        lecvar_post ("classe", post, valclasse);
    }
Les fonctions lecvar_get (...) et lecvar_post (...) utilisent avec la même liste de paramètres :
  1. Le nom de la variable du formulaire dont on veut récupérer la valeur.
  2. La variable qui contient la liste des variables du formulaire avec leurs valeurs.
  3. La variable qui va stocker la valeur trouvée.
Comme 2ème paramètre, on utilise pour lecvar_get (...) la variable qui était le 2ème paramètre de la fonction lire_trame_client (...) et pour lecvar_post (...) la variable qui était le 4ème paramètre de cette fonction.

Remarque : Le formulaire qui a permit de saisir les 2 valeurs autorisait pour chacune 20 caractères :
    <input type="text" name="nom" maxlength="20" ...>
    ...
    <input type="text" name="classe" maxlength="20" ...>
Les variables qui mémorisent ces valeurs utilisent un caractère de plus :
    char valnom [21], valclasse [21];
Ce caractère supplémentaire est nécessaire compte tenu de la manière dont sont mémorisées les chaines de caractères en langage C.

On a récupéré les informations saisies par l'utilisateur. On va les afficher dans une nouvelle page HTML qui est construite à partir du fichier repget.ahp ou reppost.ahp selon le mode de transmission des valeurs saisies.

Le contenu de ces 2 fichiers ne diffère qu'au niveau de leur titre et des liens en bas de page. Voici le code source du premier :



La partie du code source qui nous intéresse est celle-ci :
    <p style="font-size : 30" align="center">
        Bonjour XXXNOM
        de XXXCLASSE
    </p>
Il faut d'abord remplacer XXXNOM par le nom saisi pat l'utilisateur dans le formulaire. Mais il peut très bien n'en avoir saisi aucun ! Dans ce cas, on va l'appeler "inconnu".
    // si nom inconnu
    if (! *valnom)
        // l'initialiser
        strcpy (valnom, "inconnu");
Tout est prêt pour recopier le début du fichier AHP (qui contient du HTML) jusqu'à la ligne qui contient XXXNOM en remplaçant XXXNOM par la valeur du nom mémorisé. Cela se fait en utilisant la même fonction que pour le programme "compteur de passages".
    // copier la page HTML jusqu'à l'affichage du nom
    coprep_chaine (descfic, client, "XXXNOM", valnom);
A présent, on va s'occuper de la 2ème valeur mémorisée. Mais le traitement va être différent si l'utilisateur n'a rien saisi pour la classe dont il fait partie.
    // si classe inconnue
    if (! *valclasse)
        // sauter l'indication de la classe
        sauter_jusque_chaine (descfic, "XXXCLASSE");
    // sinon
    else
        // copier avec le nom de la classe
        coprep_chaine (descfic, client, "XXXCLASSE", valclasse);
Si la variable valclasse est vide, on utilise une nouvelle fonction :
    sauter_jusque_chaine (descfic, "XXXCLASSE");
Cette fonction lit les lignes du fichier AHP à partir de celle où on s'était arrêté précédemment, jusqu'à la ligne qui contient XXXCLASSE mais renvoie pas ces lignes vers le navigateur web.

Dans le cas particulier des fichiers repget.ahp et reppost.ahp, comme la partie du fichier AHP qu'on ne veut pas envoyer au navigateur se limite à la ligne qui suit l'endroit où on s'était arrêté, une autre instruction aurait pu réaliser le même travail :
    lire_ligne (descfic);
Dans le cas où la variable valclasse contient une chaine de caractères, on utilise comme pour la variable valnom la fonction coprep_chaine (...) pour remplacer XXXCLASSE par le bon contenu.

Dans le code source des fichier AHP, le message
        Bonjour XXXNOM
        de XXXCLASSE
est sur 2 lignes. Mais comme il n'y a pas de balise de passage à la ligne après le nom, tout le texte apparaitra sur la même ligne dans la fenêtre du navigateur (sauf si la largeur de cette fenêtre est très faible).

Selon que l'utilisateur ait ou non saisi une information pour sa classe, la chaine de caractère affichée sera de la forme :
ou seulement On a fini avec les traitements spécifiques aux fichiers AHP. Le déroulement du programme se poursuit avec l'instruction :
    // envoi de la page ou de la fin de page
    copie_jusque_fin (descfic, client);
Dans le cas d'un fichier AHP, on s'était arrêté à la ligne :
    </p>
et cette instruction renvoie au navigateur la fin du fichier AHP à partir de cette ligne là.

Si au contraire, on doit envoyer un fichier HTML, les traitements concernant la récupération des valeurs du formulaire et leurs affichage n'ont pas été effectués :
    // si page de réponse à un formulaire
    if (memcmp (url, "rep", 3) == 0)
    {
    }

    // envoi de la page ou de la fin de page
    copie_jusque_fin (descfic, client);
et dans ce cas, la fonction copie_jusque_fin () envoie la totalité du contenu du fichier HTML au navigateur.