OpenScheme : Script CGI en Scheme
Par :
Guilhem de Wailly (gdw@erian-concept.com)

et :
Fernand Boéri (boeri@unice.fr)

Résumé
Notre connaissance du langage Scheme nous permet maintenant d'entrevoir toute la puissance de ce langage en concevant des applications plus complexes. Cela est rendu possible en exploitant les possibilités d'OpenScheme couvrant un large spectre de fonctionnalités.
Ce mois-ci, nous examinerons comment écrire les scripts CGI et FastCGI en OpenScheme. Nous commençons par examiner très sommairement le protocole HTTP et l'interface CGI. Puis nous écrirons notre premier CGI en OpenScheme. Puis nous examinerons les fonctionnalités CGI de l'environnement, contenues dans la bibliothèque NET.
La description qui est faite ici du protocole HTTP sera réutilisée lorsque nous réaliserons notre serveur WEB en OpenScheme.
L'environnement OpenScheme est disponible sur le CDROM de Linux Magazine. Il est aussi disponible sur www.open-scheme.com. Cet environnement existe en version libre ou commerciale.
HTTP ``statique''
Le principe des scripts CGI a déjà été décrit par Pierre Ficheux dans Le premier Linux Magazine. Aussi, nous ne reviendrons là dessus que succinctement.
Un serveur WEB est, grosso-modo, un programme qui scrute des requêtes sur une entrée et qui produit un résultat en sortie. Les requêtes sont sous la forme de mots clefs suivis d'arguments. Les sorties sont sous la forme de texte au format HTML. Les entrées/sorties d'un serveur WEB se font au travers des sockets qui permettent les connexions entre machines distantes. Le numéro du port est 80 par convention, mais il est possible d'utiliser d'autres ports.
Le protocole HTTP est en mode non connecté ; cela signifie que la connexion est fermée après l'obtention du résultat d'une requête. Cela permet au serveur WEB de ne pas stocker d'état interne d'une connexion, ce qui accélère les traitements et diminue le besoin en mémoire.
Il est tout à fait possible d'interroger un serveur WEB avec l'outil telnet, en ouvrant le port 80:
$ telnet www.erian-concept.com 80
GET /

<HTML>
<HEAD>
<TITLE>Erian Concept - Linux assistance</TITLE>
<META NAME="Author" CONTENT="Guilhem de Wailly">
</HEAD>

<FRAMESET ROWS="85,*"
          FRAMEBORDERS="NO"
          FRAMESPACING=0
          BORDER=0>
<FRAME NAME="head"
       SRC="head.htm"
       NORESIZE
       SCROLLING="NO">
<FRAME NAME="body"
       SRC="body-fr.htm"
       SCROLLING="YES">
</FRAMESET>
</HTML>
La première requête, la plus simple, est le GET qui demande l'obtention d'une ressource. Lorsque que la requête n'est pas suivie du numéro de version, il s'agit d'un client en version HTTP 0.9, sinon la version suit la ressource (GET / HTTP/1.0). La requête est suivie par une ligne blanche pour être prise en compte par le serveur ; cela permet de donner des arguments supplémentaires, comme des informations d'authentification. 
En réponse à une requête, le serveur retourne la ressource demandée ; si elle n'existe pas, un message d'erreur est retourné. La réponse du serveur est du texte au format HTML.
Les requêtes peuvent être assorties d'un en-tête inséré entre la requête et la ligne blanche. Cet en-tête permet de passer un certain nombre de paramètres aux serveurs.
Il existe d'autres types de requêtes :
GET ressource HTTP/1.0
Nous avons déjà vu le GET. Des arguments peuvent être assortis à la ressource demandée en introduisant le premier argument avec un point d'interrogation et les arguments suivants avec un et commercial. Il est possible de spécifier la valeur de l'argument en séparant le nom de l'argument de sa valeur par le signe égal :
GET /ressource?premier_argument
ou :
GET /ressource?premier_argument&argument_suivant=valeur
Le format des arguments est libre ; cependant des guillemets doivent être utilisés lorsque des espaces sont inclus dans les noms ou les valeurs.
HEAD ressource HTTP/1.0
La requête HEAD ne retourne pas le corps de la ressource, mais seulement son en-tête. Cela permet d'obtenir des informations de mise à jour des ressources sans avoir à récupérer la totalité de la ressource.
Par exemple :
$ telnet www.erian-concept.com 80
HEAD / HTTP/1.0

HTTP/1.1 200 OK
Date: Thu, 05 Oct 2000 09:53:38 GMT
Server: Apache/1.3 (Unix)
Last-Modified: Fri, 17 Mar 2000 12:49:19 GMT
ETag: "97852-33c-38d229cf"
Accept-Ranges: bytes
Content-Length: 828
Connection: close
Content-Type: text/html

Connection closed by foreign host.
POST ressource HTTP/1.0
La méthode GET est principalement définie pour récupérer des ressources depuis le serveur. Mais comme il est possible de rajouter des arguments après le nom de la ressource, elle peut aussi être employée pour envoyer des informations sur le serveur, comme il est nécessaire de le faire lorsque l'on remplit un formulaire.
Cependant, la longueur de la requête a une limite et il est préférable d'utiliser la méthode POST pour envoyer des informations sur le serveur. Dans ce cas, les informations sont envoyées dans l'en-tête de la requête. 
Cette méthode envoie des données vers la ressource spécifiée, généralement un script CGI.
PUT ressource HTTP/1.0
Replace la ressource située sur le serveur par les données qui sont envoyées. Cette requête nécessite des droits particuliers pour être acceptée et exécutée par le serveur.
DELETE ressource HTTP/1.0
Supprime la ressource sur le serveur. Cette requête nécessite des droits particuliers pour être acceptée et exécutée par le serveur.
HTTP ``dynamique''
Cette forme d'interrogation est statique dans la mesure ou les sorties sont identiques pour une même requête.
Pour introduire un peu de dynamisme, les premiers concepteurs des serveurs WEB ont conçu un système qui permet de transmettre les requêtes à des programmes externes au serveur WEB, appelés CGI (Common Gateway Interface). Le protocole utilisé pour passer les arguments à ces programmes et récupérer leurs résultats est très simple et très facile à réaliser dans des environnements UNIX.
Avec ces programmes CGI, le WEB devient dynamique car les pages affichées sont générées à partir d'un état interne du serveur WEB, en général une base de donnée ou toute autre information stockée.
Le très gros avantage des CGI est donc la grande simplicité dans le protocole d'échange et le fait qu'il est complètement indépendant de tout langage de programmation : on peut écrire des CGI en Shell, en Perl, en Python, en Pascal, en C, en assembleur :) ou en ... Scheme.
Le problème inhérent au CGI est leur relative lenteur : en effet, le programme CGI est exécuté à chaque requête par le système d'exploitation. Dans le cas d'in langage interprété, l'interprète est chargé et initialisé à chaque requête.
La première alternative au CGI est le FastCGI qui repose sur le même principe que le CGI. Mais ,au lieu d'exécuter le programme pour chaque requête, celui-ci est construit sur une boucle infinie lisant les entrées et produisant les sorties. Là encore, le très gros avantage est de permettre une indépendance totale avec le langage de programmation tout en donnant de bonnes performances.
La deuxième alternative à CGI est l'utilisation de modules qui s'incorporent aux serveurs WEB et qui fonctionnent autour d'une boucle lisant les entrées et produisant les sorties. On connaît de tels modules pour le langage Perl, Python, PHP. OpenScheme dispose lui aussi d'un tel module, mais nous ne l'avons pas encore rendu public car nous préférons l'interface FastCGI, plus générale. Les serveurs WEB de Bill utilisent aussi ce système connu sous le nom d'ASP. Mais, bien entendu, ces serveurs sont beaucoup moins puissants que des serveurs Unix en général, et Linux en particulier :)
L'inconvénient des modules est qu'ils sont réalisés pour chaque langage et pour chaque type de serveur. Leur gros avantage est de permettre de bonnes performances et d'être généralement intégré dans Apache, sans avoir à les installer ultérieurement.
CGI, base
Le premier CGI que nous écrirons sera en ... Shell. Ceci afin de nous assurer que le serveur fonctionne correctement.
Le lecteur devra au préalable installer le serveur Apache sur sa machine et s'assurer qu'il fonctionne correctement. Pour cela, il ouvrira dans un navigateur l'adresse http://127.0.0.1 ; ceci ne doit pas afficher d'erreur et indiquer que le serveur est correctement installé.
Nous allons proposer une installation simpliste afin de simplifier les explications et avoir une plate-forme commune. Chaque utilisateur pourra, en fonction de ses connaissances, adapter ce texte à ses besoins. Pour les utilisateurs plus avancés, il est possible de procéder avec un hôte virtuel, parfaitement géré par Apache.
Si le serveur est correctement installé, il est capable d'exécuter des scripts CGI. Ceux-ci sont rassemblés dans le répertoire /home/httpd/cgi-bin. 
Nous allons créer un scripts de test en Shell placé dans le fichier /home/httpd/cgi-bin/test.cgi :
#! /bin/sh

cat << EOF
Content-type: text/html

<HTML>
<BODY>
<br>Ce test fonctionne parfaitement.
<br>Nous sommes le $(date)
</BODY>
</HTML>
EOF
Ce programme indique que l'interprète /bin/sh doit être utilisé pour l'exécuter. Il lance la commande Unix cat qui affiche sur la sortie du programme toutes les lignes suivantes jusqu'à ce que le mot clef EOF soit rencontré. Le texte affiché est alors celui contenu entre les deux EOF. L'en-tête de ce texte est très important et il indique au navigateur qu'il s'agit de texte brut ou de texte codé en HTML. Puis on rencontre la balise d'ouverture d'une page WEB suivit de son corps. La commande Unix date est exécutée et son résultat est inséré tel quel dans le texte de sortie.
Pour le tester, nous entrons l'adresse http://localhost/cgi-bin/test.cgi ; ça devrait afficher le message et la date du jour.
L'étape suivante consiste à créer le script en OpenScheme. Pour cela, vous devez avoir une version de l'environnement sur votre système. Les commandes qui suivent doivent être exécutées en tant que l'utilisateur root.
·	Si vous avez installé la version complète, vous devriez avoir le fichier _osm_c.version sur votre système ; il s'agit de la version statique contenant tous les plugins et en vérification des types d'OpenScheme. Par défaut, il se situe dans /usr/local/osm-version/bin/x86/Linux/. Copiez le en /usr/local/bin/osm-cgi.
·	Si vous n'avez pas d'environnement sur votre système, ou bien si vous avez une ancienne version, récupérez le fichier osm-Linux-x86-1.3.4-light sur le site http://www.open-scheme.com/download.htm. Copiez le en /usr/local/bin/osm-cgi.
Vérifiez bien que le binaire est exécutable pour tout le monde. Pour cela, vérifiez que la commande ls -la /usr/local/bin/osm-cgi affiche -rwxr-xr-x ou -rwxrwxr-x. Si ce n'est pas le cas, tapez la commande chmod /usr/local/bin/osm-cgi 755.
Ecrivons maintenant le premier programme CGI en Scheme dans le fichier /home/httpd/cgi-bin/osm1.cgi :
#! /usr/local/bin/osm-cgi --exec

(use 'osm)

(format #t
"Content-type: text/html

<HTML>
<BODY>
<br>Ce test osm fonctionne bien.
<br>Aujourd'hui = ~a
</BODY>
</HTML>
" (date->string (date)))
La première ligne de ce programme indique quels sont les arguments à donner à l'interprète Scheme pour exécuter le script. Ce fichier doit être rendu exécutable. Pour cela, taper la commande chmod 755 /home/httpd/cgi-bin/osm1.cgi.
Assurez-vous qu'il fonctionne correctement, indépendamment du serveur Apache en tapant la commande /home/httpd/cgi-bin/osm1.cgi. Cela doit afficher du texte en HTML !
Maintenant, nous pouvons tester avec le serveur. En utilisant le navigateur lynx, par exemple, tapez lynx http://localhost/cgi-bin/osm1.osm. On doit avoir le texte suivant affiché :
Ce test osm fonctionne bien.
Aujourd'hui = Sat Oct 7 16:00:12 2000
Nous sommes maintenant prêts à exploiter les fonctions CGI d'OpenScheme !
Ces fonctionnalités sont regroupées dans le module NET. Elles permettent de remplacer une série de mots clefs d'une page WEB par une valeur. Dans ce mode de fonctionnement, on utilise une page WEB existante, dans laquelle on place les mots clefs. 
Il est aussi possible de placer du code Scheme directement dans une page WEB, comme on le fait avec ASP, PHP ou Perl. De cette manière, le texte HTML et les programmes se situent dans le même fichier. La bibliothèque permet aussi de récupérer la valeur des champs des formulaires dans des variables Scheme, sans intervention, ainsi que les principales variables d'environnement.
Nous verrons tout cela la prochaine fois...
Les auteurs

Guilhem de Wailly, directeur de la société Erian Concept : support, formations, configurations, administration, développements Linux. Environnement OpenScheme.
http://www.erian-concept.com

Pr Fernand Boéri, Professeur à l'Université de Nice - Sophia-Antipolis, membre de l'unité SPORTS du laboratoire I3S, spécialiste en modélisation, évaluation de performances et architectures parallèles.
http://www.i3s.unice.fr
Références
WEB
¨	TCP/IP, Architecture, protocoles, applications
Douglas Comer
InterEdition
·	W3C
http://www.w3c.org
·	CGI
http://www.jmarshall.com/easy/cgi/
·	CGI
http://hoohoo.ncsa.uiuc.edu/cgi/
·	CGI
http://www.tsden.org/ryutaroh/fileupload-e.shtml
·	CGI en Français
http://www.scripts-fr.com/
·	CGI+Scheme
http://www.lh.com/~oleg/ftp/Scheme/web.html
·	FastCGI
http://www.fastcgi.com/
·	HTTP en Français
http://webbo.enst-bretagne.fr/ActiveWebFr/eg-uk-tut.book_29.fr.html
·	HTTP 1.0
http://www.ietf.org/rfc/rfc1945.txt
·	HTTP 1.1
http://www.ietf.org/rfc/rfc2616.txt
Scheme
¨	Structure et Interprétation des programmes informatiques
H. Abelson, GJ. Sussman
InterEdition
¨	The Scheme Programming Languages - Ansi Scheme 
R. Kent Dybvig
Prentice Hall
¨	Les langages Lisps - Christian Queinnec
InterEdition
¨	Programmer avec Scheme - J. Chazarin
Thomson Publishing
¨	Revised4 Report on the Algorithmic Language Scheme
W. Clinger, J. Rees
ftp://ftp.nj.nec.com/pub/kelsey
Environnements Scheme Free
¨	Bigloo - Manuel Serrano
http://kaolin.unice.fr
Environnement de programmation Scheme.
¨	DrScheme - Rice University
http://www.cs.rice.edu/CS/PLT/
Environnement Scheme libre très avancé.
¨	PCScheme - Texas Instrument
ftp://cui.unige.ch/public/pcs/pcscheme.exe
Un très bon environnement de programmation Scheme pour DOS, avec éditeur intégré.
¨	Scm - A. Jaffer
http://www-swiss.ai.mit.edu/~jaffer
La référence des interprètes Scheme. Très petit, rapide, pour beaucoup de plates-formes, extensible.
¨	Stk - Erik Gallesio
http://kaolin.unice.fr
Interprète Scheme avec la bibliothèque TK.
D'autres liens sont visibles sur le site www.schemers.org.
Environnements Scheme commerciaux
¨	ChezScheme - Cadence, Inc
http://www.scheme.com/
Environnement Scheme très performant.
¨	EdScheme, 3Dscheme - Scheme, Inc
http://www.schemers.com/
Environnement de programmation Scheme pour Windows.
¨	Inlab Scheme - Inlab Software GmbH
http://www.munich.net/inlab/scheme/
Environnement commercial
¨	OpenScheme - Erian Concept
http://www.open-scheme.com
Environnement professionnel de programmation Scheme comprenant un interprète, un compilateur et un débogueur symbolique. 
Existe en version libre et commerciale, pour Linux, FreeBSD, Solaris, Windows et BeOS, sur systèmes Intel.