Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Langue C

Maîtriser la programmation Web C++ avec CGI

Qu'est-ce que le CGI ?

L'Interface de passerelle commune (CGI) est un ensemble de normes définissant l'échange d'informations entre le serveur web et un script personnalisé. Les spécifications CGI sont maintenues par le NCSA.

Le CGI permet à des programmes externes (scripts CGI) d'interagir avec les serveurs d'information comme les serveurs HTTP. Ces programmes peuvent être écrits en Python, Perl, Shell, C, C++, etc. La version actuelle est CGI/1.1.

Navigation web et CGI

Lorsqu'on clique sur un lien :

  1. Le navigateur contacte le serveur HTTP et demande l'URL (nom de fichier).
  2. Le serveur analyse l'URL, cherche le fichier. S'il le trouve, il l'envoie ; sinon, il renvoie une erreur.
  3. Le navigateur affiche le fichier reçu ou le message d'erreur.

On peut configurer le serveur pour qu'au lieu d'envoyer un fichier, il l'exécute comme un programme et renvoie sa sortie au navigateur. C'est le principe du CGI.

Architecture CGI

Maîtriser la programmation Web C++ avec CGI

Configuration du serveur web

Avant de programmer en CGI, vérifiez que votre serveur le supporte et est configuré pour exécuter les programmes CGI. Par convention, les programmes CGI résident dans /var/www/cgi-bin et portent l'extension .cgi (même s'il s'agit d'exécutables C++).

Pour Apache, la configuration typique dans httpd.conf :

<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options ExecCGI
    Order allow,deny
    Allow from all
</Directory>
<Directory "/var/www/cgi-bin">
    Options All
</Directory>

Premier programme CGI en C++

#include <iostream>
using namespace std;

int main() {
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n";
    cout << "<head>\n";
    cout << "<title>Hello World - Premier programme CGI</title>\n";
    cout << "</head>\n";
    cout << "<body>\n";
    cout << "<h2>Hello World! Ceci est mon premier programme CGI</h2>\n";
    cout << "</body>\n";
    cout << "</html>\n";
    return 0;
}

Compilez et nommez l'exécutable cplusplus.cgi. Placez-le dans /var/www/cgi-bin et rendez-le exécutable :

chmod 755 cplusplus.cgi

Point crucial : l'en-tête HTTP

La première ligne Content-type:text/html\r\n\r\n est obligatoire. Elle indique au navigateur le type de contenu (MIME). Sans elle, le navigateur ne saura pas comment afficher la sortie.

En-têtes HTTP courants

En-têteDescription
Content-typeType MIME du contenu (ex: text/html).
ExpiresDate d'expiration du contenu (format: 01 Jan 1998 12:00:00 GMT).
LocationURL de redirection.
Last-modifiedDate de dernière modification de la ressource.
Content-lengthTaille en octets des données renvoyées.
Set-CookieDéfinit un cookie.

Variables d'environnement CGI

Les programmes CGI accèdent à de nombreuses variables d'environnement :

VariableDescription
CONTENT_TYPEType de données envoyées par le client (ex: upload de fichier).
CONTENT_LENGTHLongueur des données (requêtes POST).
HTTP_COOKIECookies envoyés par le client.
HTTP_USER_AGENTNavigateur/client utilisé.
PATH_INFOChemin du script CGI.
QUERY_STRINGDonnées encodées en URL (méthode GET).
REMOTE_ADDRAdresse IP du client.
REMOTE_HOSTNom d'hôte du client.
REQUEST_METHODMéthode HTTP (GET, POST, etc.).
SCRIPT_FILENAMEChemin complet du script CGI.
SCRIPT_NAMENom du script CGI.
SERVER_NAMENom d'hôte ou IP du serveur.
SERVER_SOFTWARELogiciel serveur et version.

Exemple : lister toutes les variables d'environnement

#include <iostream>
#include <stdlib.h>
#include <string>
#include <vector>

using namespace std;

const string ENV[24] = {
    "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
    "HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE",
    "HTTP_CONNECTION", "HTTP_HOST", "HTTP_USER_AGENT",
    "PATH", "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",
    "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
    "SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN",
    "SERVER_NAME", "SERVER_PORT", "SERVER_PROTOCOL",
    "SERVER_SIGNATURE", "SERVER_SOFTWARE"
};

int main() {
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html><head><title>Variables d'environnement CGI</title></head><body>";
    cout << "<table border=\"0\" cellspacing=\"2\">";
    for (int i = 0; i < 24; i++) {
        cout << "<tr><td>" << ENV[i] << "</td><td>";
        char *value = getenv(ENV[i].c_str());
        if (value) cout << value;
        else cout << "Variable d'environnement inexistante.";
        cout << "</td></tr>\n";
    }
    cout << "</table></body></html>";
    return 0;
}

Bibliothèque CGI pour C++ (cgicc)

Pour des applications réelles, utilisez la bibliothèque cgicc (GNU) :

$ tar xzf cgicc-X.X.X.tar.gz
$ cd cgicc-X.X.X/
$ ./configure --prefix=/usr
$ make
$ make install

Documentation : C++ CGI Lib Documentation.

Méthodes GET et POST

Deux méthodes principales pour transmettre des données du navigateur au serveur :

Méthode GET

Les données sont ajoutées à l'URL après ? :

https://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2

Exemple GET avec cgicc

URL : /cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>

using namespace std;
using namespace cgicc;

int main() {
    Cgicc formData;
    cout << HTTPHTMLHeader() << endl;
    cout << "<html><head><title>Méthodes GET et POST</title></head><body>";

    form_iterator fi = formData.getElement("first_name");
    if (!fi->isEmpty() && fi != (*formData).end()) {
        cout << "Prénom : " << **fi << "<br/>";
    } else {
        cout << "Aucun prénom saisi<br/>";
    }

    fi = formData.getElement("last_name");
    if (!fi->isEmpty() && fi != (*formData).end()) {
        cout << "Nom : " << **fi << "<br/>";
    } else {
        cout << "Aucun nom saisi<br/>";
    }

    cout << "</body></html>";
    return 0;
}

Compilation : g++ -o cpp_get.cgi cpp_get.cpp -lcgicc

Exemple formulaire HTML GET

<form action="/cgi-bin/cpp_get.cgi" method="get">
    Prénom: <input type="text" name="first_name"><br/>
    Nom: <input type="text" name="last_name" />
    <input type="submit" value="Soumettre" />
</form>

Méthode POST

Plus fiable : les données sont envoyées dans le corps de la requête (entrée standard), pas dans l'URL. Pas de limite de taille pratique. Le même script CGI gère GET et POST avec cgicc.

Exemple formulaire HTML POST

<form action="/cgi-bin/cpp_get.cgi" method="post">
    Prénom: <input type="text" name="first_name"><br/>
    Nom: <input type="text" name="last_name" />
    <input type="submit" value="Soumettre" />
</form>

Cas particuliers de formulaires

Cases à cocher (checkboxes)

Permettent de sélectionner plusieurs options.

<form action="/cgi-bin/cpp_checkbox.cgi" method="POST">
    <input type="checkbox" name="maths" value="on" /> Maths
    <input type="checkbox" name="physics" value="on" /> Physique
    <input type="submit" value="Sélectionner" />
</form>

Traitement avec formData.queryCheckbox("nom").

Boutons radio

Un seul choix possible.

<form action="/cgi-bin/cpp_radiobutton.cgi" method="post">
    <input type="radio" name="subject" value="maths" checked="checked"/> Maths
    <input type="radio" name="subject" value="physics" /> Physique
    <input type="submit" value="Sélectionner" />
</form>

Traitement avec formData.getElement("subject").

Zone de texte (textarea)

Pour du texte multiligne.

<form action="/cgi-bin/cpp_textarea.cgi" method="post">
    <textarea name="textcontent" cols="40" rows="4">Votre texte...</textarea>
    <input type="submit" value="Soumettre" />
</form>

Liste déroulante (dropdown)

<form action="/cgi-bin/cpp_dropdown.cgi" method="post">
    <select name="dropdown">
        <option value="Maths" selected>Maths</option>
        <option value="Physique">Physique</option>
    </select>
    <input type="submit" value="Soumettre"/>
</form>

Utilisation des cookies en CGI

HTTP est sans état. Les cookies permettent de maintenir des informations de session entre les pages.

Fonctionnement

Le serveur envoie un cookie au navigateur. S'il l'accepte, il le stocke localement. À la prochaine visite, le cookie est renvoyé au serveur.

Un cookie comporte 5 champs : Expires, Domain, Path, Secure, Name=Value.

Définir des cookies

Les cookies sont envoyés avant la ligne Content-type via l'en-tête Set-Cookie :

#include <iostream>
using namespace std;

int main() {
    cout << "Set-Cookie:UserID=XYZ;\r\n";
    cout << "Set-Cookie:Password=XYZ123;\r\n";
    cout << "Set-Cookie:Domain=www.exemple.com;\r\n";
    cout << "Set-Cookie:Path=/cgi;\n";
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html><head><title>Cookies en CGI</title></head><body>";
    cout << "Cookies définis<br/></body></html>";
    return 0;
}

Récupérer les cookies

Ils sont dans la variable d'environnement HTTP_COOKIE sous forme clé1=valeur1; clé2=valeur2; .... Avec cgicc :

#include <iostream>
#include <vector>
#include <string>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>

using namespace std;
using namespace cgicc;

int main() {
    Cgicc cgi;
    const CgiEnvironment& env = cgi.getEnvironment();
    cout << HTTPHTMLHeader() << "<html><head><title>Cookies</title></head><body>";
    cout << "<table border=\"0\" cellspacing=\"2\">";
    for (const_cookie_iterator cci = env.getCookieList().begin();
         cci != env.getCookieList().end(); ++cci) {
        cout << "<tr><td>" << cci->getName() << "</td><td>";
        cout << cci->getValue() << "</td></tr>\n";
    }
    cout << "</table></body></html>";
    return 0;
}

Upload de fichiers

Le formulaire doit avoir enctype="multipart/form-data" :

<form enctype="multipart/form-data" action="/cgi-bin/cpp_uploadfile.cgi" method="post">
    <p>Fichier: <input type="file" name="userfile" /></p>
    <p><input type="submit" value="Téléverser" /></p>
</form>

Script de traitement :

#include <iostream>
#include <vector>
#include <string>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>

using namespace std;
using namespace cgicc;

int main() {
    Cgicc cgi;
    cout << HTTPHTMLHeader() << "<html><head><title>Upload de fichier</title></head><body>";

    const_file_iterator file = cgi.getFile("userfile");
    if (file != cgi.getFiles().end()) {
        cout << HTTPContentHeader(file->getDataType());
        file->writeToStream(cout);
    }
    cout << "<p>Fichier téléversé avec succès</p>";
    cout << "</body></html>";
    return 0;
}

Vous pouvez rediriger le flux vers un fichier pour sauvegarder l'upload.

Langue C

  1. Maîtriser les espaces de noms en C# : Organisation, portée et bonnes pratiques
  2. Maîtriser les opérateurs C++ : Guide complet avec exemples pratiques
  3. Commentaires C++ : Bonnes pratiques pour un code lisible et maintenable
  4. Comment passer des tableaux aux fonctions en C++ : Guide pratique
  5. Maîtriser la programmation C : Tutoriel complet pour débutants
  6. Langage C++ : Vue d'ensemble et caractéristiques clés
  7. Constantes et littéraux en C++ : Types, syntaxe et bonnes pratiques
  8. Guide complet des opérateurs C++ : Types, utilisation et bonnes pratiques
  9. Maîtriser les types numériques en C++ : Guide pratique