Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> C Taal

C++ Webprogrammering met CGI: Volledige gids

Wat is CGI?

  • De Common Gateway Interface (CGI) is een set standaarden die definieert hoe informatie wordt uitgewisseld tussen de webserver en een aangepast script.

  • De CGI-specificaties worden beheerd door de NCSA. NCSA definieert CGI als een standaard voor externe gateway-programma's om te communiceren met informatieservers zoals HTTP-servers.

  • De huidige versie is CGI/1.1; CGI/1.2 is in ontwikkeling.

Web Browsen

Om CGI te begrijpen, kijken we wat er gebeurt wanneer we op een hyperlink klikken om een webpagina of URL op te vragen.

  • Uw browser contacteert de HTTP-webserver en vraagt de URL (bestandsnaam) op.

  • De webserver parseert de URL en zoekt het bestand. Als het gevonden wordt, stuurt de server het bestand terug; anders stuurt hij een foutmelding.

  • De browser toont het ontvangen bestand of de foutmelding.

Het is mogelijk de HTTP-server zo te configureren dat bestanden in een bepaalde map niet direct worden teruggestuurd, maar als programma worden uitgevoerd. De output van dat programma wordt dan naar de browser gestuurd.

CGI is een standaardprotocol voor het laten communiceren applicaties (CGI-programma's of -scripts) met webservers en clients. Deze programma's kunnen in Python, PERL, Shell, C, C++ etc. geschreven zijn.

CGI-architectuurdiagram

Het volgende eenvoudige diagram toont de CGI-architectuur:

C++ Webprogrammering met CGI: Volledige gids

Webserverconfiguratie

Voordat u met CGI-programmering begint, zorg ervoor dat uw webserver CGI ondersteunt en geconfigureerd is om CGI-programma's uit te voeren. Alle CGI-programma's worden in een vooraf geconfigureerde map bewaard, de CGI-directory, conventioneel /var/www/cgi-bin. CGI-bestanden hebben conventioneel de extensie .cgi, ook al zijn het C++-uitvoerbare bestanden.

Standaard is Apache geconfigureerd om CGI-programma's in /var/www/cgi-bin uit te voeren. Om een andere map op te geven, wijzigt u de 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>

Ervan uitgaande dat uw webserver draait en u andere CGI-programma's (Perl, Shell) kunt uitvoeren.

Eerste CGI-programma

Hieronder een eenvoudig C++ CGI-programma:

#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 - First CGI Program</title>\n";
    cout << "</head>\n";
    cout << "<body>\n";
    cout << "<h2>Hello World! This is my first CGI program</h2>\n";
    cout << "</body>\n";
    cout << "</html>\n";
    return 0;
}

Compileer de code en noem het uitvoerbare bestand cplusplus.cgi. Plaats het in /var/www/cgi-bin en maak het uitvoerbaar met chmod 755 cplusplus.cgi.

Mijn eerste CGI-programma

Het programma schrijft naar STDOUT (scherm). De cruciale eerste regel Content-type:text/html\r\n\r\n wordt naar de browser gestuurd en specificeert het content-type. Nu kunt u complexe CGI-programma's schrijven, bijvoorbeeld met interactie met een RDBMS.

HTTP-header

De regel Content-type:text/html\r\n\r\n maakt deel uit van de HTTP-header. Alle HTTP-headers hebben de vorm:

HTTP-veldnaam: Veldinhoud
Bijvoorbeeld: Content-type: text/html\r\n\r\n

Andere veelgebruikte HTTP-headers:

Nr. Header & Beschrijving
1

Content-type:

Een MIME-string die het formaat van het teruggegeven bestand definieert. Voorbeeld: Content-type:text/html.

2

Expires: Datum

De datum waarop de informatie ongeldig wordt. Formaat: 01 Jan 1998 12:00:00 GMT.

3

Location: URL

De URL die geretourneerd moet worden in plaats van de aangevraagde URL. Kan gebruikt worden voor redirect.

4

Last-modified: Datum

De datum van de laatste wijziging van de resource.

5

Content-length: N

De lengte in bytes van de teruggegeven data. De browser gebruikt dit voor geschatte downloadtijd.

6

Set-Cookie: String

Stelt een cookie in via de string.

CGI-omgevingsvariabelen

Alle CGI-programma's hebben toegang tot de volgende omgevingsvariabelen, die essentieel zijn bij het schrijven van CGI-programma's.

Nr. Variabelenaam & Beschrijving
1

CONTENT_TYPE

Het datatype van de inhoud, gebruikt wanneer de client bijgevoegde inhoud stuurt (bijv. bestandsupload).

2

CONTENT_LENGTH

De lengte van de query-informatie, alleen beschikbaar voor POST-verzoeken.

3

HTTP_COOKIE

Retourneert de ingestelde cookies als sleutel-waardeparen.

4

HTTP_USER_AGENT

Bevat informatie over de user agent (browser).

5

PATH_INFO

Het pad voor het CGI-script.

6

QUERY_STRING

De URL-gecodeerde informatie die met de GET-methode wordt verstuurd.

7

REMOTE_ADDR

Het IP-adres van de remote host die het verzoek doet. Nuttig voor logging of authenticatie.

8

REMOTE_HOST

De volledig gekwalificeerde hostnaam van de requester. Als niet beschikbaar, kan REMOTE_ADDR gebruikt worden.

9

REQUEST_METHOD

De methode van het verzoek (GET, POST, etc.).

10

SCRIPT_FILENAME

Het volledige pad naar het CGI-script.

11

SCRIPT_NAME

De naam van het CGI-script.

12

SERVER_NAME

De hostnaam of het IP-adres van de server.

13

SERVER_SOFTWARE

De naam en versie van de serversoftware.

Klein CGI-programma om alle CGI-variabelen te tonen:

#include <iostream>
#include <stdlib.h>
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>\n<head>\n<title>CGI Environment Variables</title>\n</head>\n<body>\n";
    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 != 0) cout << value;
        else cout << "Environment variable does not exist.";
        cout << "</td></tr>\n";
    }
    cout << "</table><\n";
    cout << "</body>\n</html>\n";
    return 0;
}

C++ CGI-bibliotheek

Voor echte toepassingen hebt u een CGI-bibliotheek nodig. Er is een C++ CGI-bibliotheek beschikbaar op ftp://ftp.gnu.org/gnu/cgicc/. Installatiestappen:

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

Documentatie vindt u bij 'C++ CGI Lib Documentation'.

GET- en POST-methodes

Browsers gebruiken twee methoden om informatie door te geven aan de webserver en uiteindelijk aan uw CGI-programma: GET en POST.

Informatie doorgeven met GET

De GET-methode stuurt de gecodeerde gebruikersinformatie aangehecht aan de paginaverzoek, gescheiden door een ?:

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

GET is de standaardmethode, produceert een lange string in de adresbalk, heeft een limiet van ~1024 tekens en is ongeschikt voor gevoelige data (wachtwoorden). De informatie komt via de QUERY_STRING HTTP-header en is beschikbaar via de omgevingsvariabele QUERY_STRING.

Eenvoudig URL-voorbeeld: GET

URL die twee waarden doorgeeft aan cpp_get.cgi:

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

C++ CGI-programma met de cgicc-bibliotheek:

#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 << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>Using GET and POST Methods</title>\n</head>\n<body>\n";
    form_iterator fi = formData.getElement("first_name");
    if(!fi->isEmpty() && fi != (*formData).end()) {
        cout << "First name: " << **fi << endl;
    } else {
        cout << "No text entered for first name" << endl;
    }
    cout << "<br/>\n";
    fi = formData.getElement("last_name");
    if(!fi->isEmpty() && fi != (*formData).end()) {
        cout << "Last name: " << **fi << endl;
    } else {
        cout << "No text entered for last name" << endl;
    }
    cout << "<br/>\n</body>\n</html>\n";
    return 0;
}

Compileren:

$ g++ -o cpp_get.cgi cpp_get.cpp -lcgicc

Plaats cpp_get.cgi in uw CGI-directory en open:

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

Resultaat:

First name: ZARA
Last name: ALI

Eenvoudig FORM-voorbeeld: GET

<form action="/cgi-bin/cpp_get.cgi" method="get">
First Name: <input type="text" name="first_name"><br />
Last Name: <input type="text" name="last_name" />
<input type="submit" value="Submit" />
</form>

Informatie doorgeven met POST

POST is betrouwbaarder: de informatie wordt op dezelfde manier verpakt als GET, maar als een apart bericht (standaard input) verstuurd, niet in de URL. Hetzelfde CGI-script kan zowel GET als POST afhandelen.

FORM-voorbeeld: POST

<form action="/cgi-bin/cpp_get.cgi" method="post">
First Name: <input type="text" name="first_name"><br />
Last Name: <input type="text" name="last_name" />
<input type="submit" value="Submit" />
</form>

Checkbox-data doorgeven aan CGI

Checkboxes worden gebruikt wanneer meerdere opties geselecteerd mogen worden.

<form action="/cgi-bin/cpp_checkbox.cgi" method="POST" target="_blank">
<input type="checkbox" name="maths" value="on" /> Maths
<input type="checkbox" name="physics" value="on" /> Physics
<input type="submit" value="Select Subject" />
</form>

C++ programma voor cpp_checkbox.cgi:

#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;
    bool maths_flag, physics_flag;
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>Checkbox Data to CGI</title>\n</head>\n<body>\n";
    maths_flag = formData.queryCheckbox("maths");
    if(maths_flag) cout << "Maths Flag: ON " << endl;
    else cout << "Maths Flag: OFF " << endl;
    cout << "<br/>\n";
    physics_flag = formData.queryCheckbox("physics");
    if(physics_flag) cout << "Physics Flag: ON " << endl;
    else cout << "Physics Flag: OFF " << endl;
    cout << "<br/>\n</body>\n</html>\n";
    return 0;
}

Radio-button data doorgeven aan CGI

Radio buttons voor enkelvoudige selectie.

<form action="/cgi-bin/cpp_radiobutton.cgi" method="post" target="_blank">
<input type="radio" name="subject" value="maths" checked="checked"/> Maths
<input type="radio" name="subject" value="physics" /> Physics
<input type="submit" value="Select Subject" />
</form>

C++ programma voor cpp_radiobutton.cgi:

#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 << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>Radio Button Data to CGI</title>\n</head>\n<body>\n";
    form_iterator fi = formData.getElement("subject");
    if(!fi->isEmpty() && fi != (*formData).end()) {
        cout << "Radio box selected: " << **fi << endl;
    }
    cout << "<br/>\n</body>\n</html>\n";
    return 0;
}

Tekstarea-data doorgeven aan CGI

TEXTAREA voor meervoudige tekst.

<form action="/cgi-bin/cpp_textarea.cgi" method="post" target="_blank">
<textarea name="textcontent" cols="40" rows="4"> Type your text here... </textarea>
<input type="submit" value="Submit" />
</form>

C++ programma voor cpp_textarea.cgi:

#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 << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>Text Area Data to CGI</title>\n</head>\n<body>\n";
    form_iterator fi = formData.getElement("textcontent");
    if(!fi->isEmpty() && fi != (*formData).end()) {
        cout << "Text Content: " << **fi << endl;
    } else {
        cout << "No text entered" << endl;
    }
    cout << "<br/>\n</body>\n</html>\n";
    return 0;
}

Dropdown-box data doorgeven aan CGI

Dropdown voor veel opties, één selectie.

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

C++ programma voor cpp_dropdown.cgi:

#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 << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>Drop Down Box Data to CGI</title>\n</head>\n<body>\n";
    form_iterator fi = formData.getElement("dropdown");
    if(!fi->isEmpty() && fi != (*formData).end()) {
        cout << "Value Selected: " << **fi << endl;
    }
    cout << "<br/>\n</body>\n</html>\n";
    return 0;
}

Cookies gebruiken in CGI

HTTP is staatloos. Voor commerciële sites is sessie-informatie nodig over pagina's heen. Cookies zijn efficiënt voor het onthouden van voorkeuren, aankopen, etc.

Hoe het werkt

De server stuurt data naar de browser als een cookie. De browser kan deze accepteren en opslaan als platte tekst. Bij een volgend bezoek is de cookie beschikbaar voor ophaling.

Een cookie bestaat uit 5 velden:

  • Expires – vervaldatum; leeg betekent bij sluiten browser.
  • Domain – domeinnaam van uw site.
  • Path – pad naar de map/pagina die de cookie zette; kan leeg zijn.
  • Secure – als "secure", alleen ophaalbaar via beveiligde server.
  • Name = Value – sleutel-waardeparen.

Cookies instellen

Cookies worden verstuurd met de HTTP-header Set-Cookie vóór de Content-type-regel.

#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.tutorialspoint.com;\r\n";
    cout << "Set-Cookie:Path = /perl;\n";
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>Cookies in CGI</title>\n</head>\n<body>\n";
    cout << "Setting cookies" << endl;
    cout << "<br/>\n</body>\n</html>\n";
    return 0;
}

Compileer naar setcookies.cgi en roep aan via /cgi-bin/setcookies.cgi.

Cookies ophalen

Cookies staan in de omgevingsvariabele HTTP_COOKIE als key1=value1; key2=value2; ....

#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 cgi;
    const_cookie_iterator cci;
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>Cookies in CGI</title>\n</head>\n<body>\n";
    cout << "<table border=\"0\" cellspacing=\"2\">";
    const CgiEnvironment& env = cgi.getEnvironment();
    for(cci = env.getCookieList().begin(); cci != env.getCookieList().end(); ++cci) {
        cout << "<tr><td>" << cci->getName() << "</td><td>";
        cout << cci->getValue();
        cout << "</td></tr>\n";
    }
    cout << "</table><\n<br/>\n</body>\n</html>\n";
    return 0;
}

Compileer naar getcookies.cgi en roep aan via /cgi-bin/getcookies.cgi. Resultaat toont alle ingestelde cookies.

Bestandsupload voorbeeld

HTML-formulier met enctype="multipart/form-data" en <input type="file">.

<html>
<body>
<form enctype="multipart/form-data" action="/cgi-bin/cpp_uploadfile.cgi" method="post">
<p>File: <input type="file" name="userfile" /></p>
<p><input type="submit" value="Upload" /></p>
</form>
</body>
</html>

Let op: Voorbeeld uitgeschakeld om uploads op onze server te voorkomen. U kunt het op uw eigen server testen.

Script cpp_uploadfile.cpp:

#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 cgi;
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>File Upload in CGI</title>\n</head>\n<body>\n";
    const_file_iterator file = cgi.getFile("userfile");
    if(file != cgi.getFiles().end()) {
        cout << HTTPContentHeader(file->getDataType());
        file->writeToStream(cout);
    }
    cout << "<File uploaded successfully>\n";
    cout << "</body>\n</html>\n";
    return 0;
}

De upload kan ook naar een bestand op de server worden weggeschreven.

Hopelijk heeft u deze tutorial genoten. Stuur ons gerust feedback!

C Taal

  1. Namespaces in C#: organisatie, scope en best practices
  2. C++ operators: complete gids met praktische voorbeelden
  3. C++ comments: best practices voor leesbare, onderhoudbare code
  4. Arrays doorgeven aan functies in C++: een praktische gids
  5. C-programmeren leren: Uitgebreide tutorial voor beginners
  6. C++ Programmeertaal: Overzicht & Belangrijkste Kenmerken
  7. C++ Constanten & Literals Uitgelegd: Types, Syntax en Best Practices
  8. Uitgebreide Gids voor C++ Operators: Types, Gebruik en Best Practices
  9. Numerieke Typen in C++ Beheersen: Een Praktische Gids
  10. C++ Referenties Begrijpen: Sleutelconcepten & Verschillen met Pointers
  11. C++ Templates Beheersen: Gids voor Generisch Programmeren