C++ Web Programming
What is CGI?
Common Gateway Interface (CGI) is a set of standards that defines how information is exchanged between web servers and client scripts.
The CGI specification is currently maintained by NCSA. NCSA defines CGI as follows:
Common Gateway Interface (CGI) is a The interface standard for connecting external gateway programs to information servers (such as HTTP servers).
The current version is CGI/1.1, and the CGI/1.2 version is in progress.
Web Browsing
To better understand the concept of CGI, let's click on a hyperlink, browse to a specific web page or URL, and see what happens.
Your browser contacts the HTTP web server and requests the URL, which is the file name.
The web server will parse the URL and look for the file name. If the requested file is found, the web server sends the file back to the browser, otherwise it sends an error message indicating that you requested the wrong file.
The web browser gets the response from the web server and displays the file or error message based on the response received.
However, for an HTTP server built in this way, whenever a file in the directory is requested, what the HTTP server sends back is not the file, but is executed in the form of a program. , and send the output generated by the execution back to the browser for display.
Common Gateway Interface (CGI) is a standard protocol that enables applications (called CGI programs or CGI scripts) to interact with Web servers and clients. These CGI programs can be written in Python, PERL, Shell, C or C++, etc.
CGI Architecture Diagram
The following figure demonstrates the architecture of CGI:
Web Server Configuration
Before you perform CGI programming, please make sure Your Web server supports CGI and is configured to handle CGI programs. All CGI programs executed by the HTTP server must be in the preconfigured directory. This directory is called the CGI directory and is conventionally named /var/www/cgi-bin. Although a CGI file is a C++ executable file, by convention its extension is .cgi.
By default, the Apache web server is configured to run CGI programs in /var/www/cgi-bin. If you want to specify another directory to run CGI scripts, you can modify the following section in the httpd.conf file:
<Directory "/var/www/cgi-bin"> AllowOverride None Options ExecCGI Order allow,deny Allow from all </Directory> <Directory "/var/www/cgi-bin"> Options All </Directory>
Here, we assume that the web server has been configured and can run successfully, you can run any CGI program, such as Perl or Shell, etc.
The first CGI program
Please look at the following C++ program:
#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 - 第一个 CGI 程序</title>\n"; cout << "</head>\n"; cout << "<body>\n"; cout << "<h2>Hello World! 这是我的第一个 CGI 程序</h2>\n"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
Compile the above code, name the executable file cplusplus.cgi, and save this file in the /var/www/cgi-bin directory. Before running the CGI program, please use the chmod 755 cplusplus.cgi UNIX command to modify the file mode to ensure that the file is executable. Access the executable file and you will see the following output:
Hello World! This is my first CGI program
The C++ program above is a simple program that puts The output is written on the STDOUT file, which is displayed on the screen. Here, it is worth noting that the first line outputs Content-type:text/html\r\n\r\n. This line is sent back to the browser and specifies the type of content to be displayed on the browser window. You must understand the basic concepts of CGI so that you can progress to writing more complex CGI programs using Python. C++ CGI programs can interact with any other external system (such as RDBMS).
HTTP header information
LineContent-type:text/html\r\n\r\n is part of the HTTP header information that is sent to the browser browser to better understand the page content. The form of HTTP header information is as follows:
HTTP 字段名称: 字段内容 例如 Content-type: text/html\r\n\r\n
There are also some other important HTTP header information, which are often used in your CGI programming.
Header information | Description |
---|---|
Content-type: | MIME string, Defines the returned file format. For example Content-type:text/html. |
Expires: Date | The information becomes an invalid date. Browsers use this to determine when a page needs to be refreshed. A valid date string should be in the format 01 Jan 1998 12:00:00 GMT. |
Location: URL | This URL refers to the URL that should be returned, not the requested URL. You can use this to redirect a request to an arbitrary file. |
Last-modified: Date | The last modified date of the resource. |
Content-length: N | The length of the data to be returned, in bytes. Browsers use this value to indicate the estimated download time of a file. |
Set-Cookie: String | Set the cookie via string. |
CGI environment variables
All CGI programs can access the following environment variables. These variables play a very important role when writing CGI programs.
Variable name | Description |
---|---|
CONTENT_TYPE | The data type of the content. Used when the client sends additional content to the server. For example, file upload and other functions. |
CONTENT_LENGTH | Query information length. Only available for POST requests. |
HTTP_COOKIE | Returns set cookies as key & value pairs. |
HTTP_USER_AGENT | The user agent request header field submits relevant information about the request initiated by the user, including the browser name, version and other platform-specific additional information. |
PATH_INFO | Path to the CGI script. |
QUERY_STRING | URL encoding information when sending a request through the GET method, including the parameters after the question mark in the URL. |
REMOTE_ADDR | The IP address of the remote host making the request. This is very useful for logging and authentication purposes. |
REMOTE_HOST | The fully qualified name of the host making the request. If this information is not available, REMOTE_ADDR can be used to obtain the IP address. |
REQUEST_METHOD | The method used to make the request. The most common methods are GET and POST. |
SCRIPT_FILENAME | Full path to the CGI script. |
SCRIPT_NAME | The name of the CGI script. |
SERVER_NAME | The host name or IP address of the server. |
SERVER_SOFTWARE | The name and version of the software running on the server. |
The following CGI program lists all CGI variables.
#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"; cout << "<head>\n"; cout << "<title>CGI 环境变量</title>\n"; cout << "</head>\n"; cout << "<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 << "环境变量不存在。"; } cout << "</td></tr>\n"; } cout << "</table><\n"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
C++ CGI Library
In a real world example, you would need to perform many operations via a CGI program. There is a CGI library specially written for C++ programs. We can download this CGI library from ftp://ftp.gnu.org/gnu/cgicc/ and follow the steps below to install the library:
$tar xzf cgicc-X.X.X.tar.gz $cd cgicc-X.X.X/ $./configure --prefix=/usr $make $make install
You can click C++ CGI Lib Documentation to view related library documents.
GET and POST methods
You may have encountered a situation when you need to pass some information from the browser to the Web server and finally to the CGI program. Usually the browser will use two methods to transmit this information to the web server, namely GET and POST methods.
Use the GET method to pass information
The GET method sends encoded user information appended to the page request. The page and the encoded information are separated by the ? character, as shown below:
http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2
The GET method is the default method of transmitting information from the browser to the Web server. It will generate a message in the browser's address bar. A very long string. Do not use the GET method when you are passing a password or some other sensitive information to the server. The GET method has a size limit, and up to 1024 characters can be passed in a request string.
When using the GET method, the QUERY_STRING http header is used to transfer information, which can be accessed using the QUERY_STRING environment variable in CGI programs.
You can pass information by following the URL with a simple concatenated key-value pair, or by using the GET method of the HTML <FORM> tag.
Simple URL example: Get method
The following is a simple URL that uses the GET method to pass two values to the hello_get.py program.
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
The following example generates cpp_get.cgi CGI program for processing the information given by the web browser input of. The passed information can be easily accessed by using the C++ CGI library:
#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"; cout << "<head>\n"; cout << "<title>使用 GET 和 POST 方法</title>\n"; cout << "</head>\n"; cout << "<body>\n"; form_iterator fi = formData.getElement("first_name"); if( !fi->isEmpty() && fi != (*formData).end()) { cout << "名:" << **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 << "姓:" << **fi << endl; }else{ cout << "No text entered for last name" << endl; } cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
Now, compile the above program as follows:
$g++ -o cpp_get.cgi cpp_get.cpp -lcgicc
Generate cpp_get.cgi and place it in CGI directory and try to access it using the following link:
/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI
This will produce the following results:
名:ZARA 姓:ALI
Simple form example: GET method
The following is a simple example that uses an HTML form and a submit button to pass two values. We will use the same CGI script cpp_get.cgi to handle the input.
<form action="/cgi-bin/cpp_get.cgi" method="get"> 名:<input type="text" name="first_name"> <br /> 姓:<input type="text" name="last_name" /> <input type="submit" value="提交" /> </form>
The following is the actual output of the above form, please enter the first and last name, and then click the submit button to view the results.
Use the POST method to transfer information
A more reliable method of transferring information to a CGI program is the POST method. This method packages the information in the same way as the GET method, except that instead of passing the information as a text string after the ? in the URL, it passes it as a separate message. This message is passed to the CGI script as standard input.
We also use the cpp_get.cgi program to handle the POST method. Let's take the same example and pass two values by using an HTML form and a submit button, except this time instead of using the GET method, we use the POST method as follows:
<form action="/cgi-bin/cpp_get.cgi" method="post"> 名:<input type="text" name="first_name"><br /> 姓:<input type="text" name="last_name" /> <input type="submit" value="提交" /> </form>
To CGI program Passing checkbox data
We use checkboxes when multiple options need to be selected.
The following HTML code example is a form with two checkboxes:
<form action="/cgi-bin/cpp_checkbox.cgi" method="POST" target="_blank"> <input type="checkbox" name="maths" value="on" /> 数学 <input type="checkbox" name="physics" value="on" /> 物理 <input type="submit" value="选择学科" /> </form>
The following C++ program will generate the cpp_checkbox.cgi script, which is used to process the checkbox passed by the web browser. input given by the box.
#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"; cout << "<head>\n"; cout << "<title>向 CGI 程序传递复选框数据</title>\n"; cout << "</head>\n"; cout << "<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"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
Pass radio button data to CGI program
We use radio buttons when only one option needs to be selected.
The following HTML code example is a form with two radio buttons:
<form action="/cgi-bin/cpp_radiobutton.cgi" method="post" target="_blank"> <input type="radio" name="subject" value="maths" checked="checked"/> 数学 <input type="radio" name="subject" value="physics" /> 物理 <input type="submit" value="选择学科" /> </form>
The following C++ program will generate the cpp_radiobutton.cgi script, which is used to process the radio button passed by the web browser. The input given by the button.
#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"; cout << "<head>\n"; cout << "<title>向 CGI 程序传递单选按钮数据</title>\n"; cout << "</head>\n"; cout << "<body>\n"; form_iterator fi = formData.getElement("subject"); if( !fi->isEmpty() && fi != (*formData).end()) { cout << "Radio box selected: " << **fi << endl; } cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
Passing text area data to CGI programs
When we need to pass multiple lines of text to CGI programs, we use the TEXTAREA element.
The following HTML code example is a form with a TEXTAREA box:
<form action="/cgi-bin/cpp_textarea.cgi" method="post" target="_blank"> <textarea name="textcontent" cols="40" rows="4"> 请在这里输入文本... </textarea> <input type="submit" value="提交" /> </form>
The following C++ program will generate the cpp_textarea.cgi script for processing the text area given by the web browser. enter.
#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"; cout << "<head>\n"; cout << "<title>向 CGI 程序传递文本区域数据</title>\n"; cout << "</head>\n"; cout << "<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"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
Pass drop-down box data to CGI program
We use drop-down boxes when multiple options are available, but only one or two options can be selected.
The following HTML code example is a form with a drop-down box:
<form action="/cgi-bin/cpp_dropdown.cgi" method="post" target="_blank"> <select name="dropdown"> <option value="Maths" selected>数学</option> <option value="Physics">物理</option> </select> <input type="submit" value="提交"/> </form>
The following C++ program will generate the cpp_dropdown.cgi script, which is used to process the information given by the web browser through the drop-down box. enter.
#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"; cout << "<head>\n"; cout << "<title>向 CGI 程序传递下拉框数据</title>\n"; cout << "</head>\n"; cout << "<body>\n"; form_iterator fi = formData.getElement("dropdown"); if( !fi->isEmpty() && fi != (*formData).end()) { cout << "Value Selected: " << **fi << endl; } cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
Using Cookies in CGI
HTTP protocol is a stateless protocol. But for a commercial website, it needs to maintain session information between different pages. For example, a user ends registration after completing multiple pages of steps. But how to maintain the user's session information across all web pages.
In many cases, using cookies is the most effective method of remembering and tracking information about user preferences, purchases, commissions, and other information needed in pursuit of a better visitor experience or site statistics.
How it works
The server sends some data to the visitor's browser in the form of a cookie. If the browser accepts the cookie, the cookie is stored as a plain-text record on the visitor's hard drive. Now, when the visitor visits another page on the website, the cookie is retrieved. Once the cookie is found, the server knows what is stored.
A cookie is a plain text data record with 5 variable-length fields:
Expires: The expiration date of the cookie . If this field is left blank, the cookie will expire when the visitor exits the browser.
Domain : The domain name of the website.
#Path : The path to the directory or web page where cookies are set. This field can be left blank if you want to retrieve cookies from any directory or web page.
Secure : If this field contains the word "secure", the cookie can only be retrieved through a secure server. If this field is left blank, this restriction does not exist.
Name=Value : Cookies are set and retrieved in the form of key-value pairs.
Set Cookies
Sending cookies to your browser is very simple. These cookies are sent along with the HTTP header before the Content-type field. Suppose you want to set UserID and Password as cookies, the steps to set cookies are as follows:
#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.w3cschool.cc;\r\n"; cout << "Set-Cookie:Path=/perl;\n"; cout << "Content-type:text/html\r\n\r\n"; cout << "<html>\n"; cout << "<head>\n"; cout << "<title>CGI 中的 Cookies</title>\n"; cout << "</head>\n"; cout << "<body>\n"; cout << "设置 cookies" << endl; cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
From this example, we understand how to set cookies. We use the Set-Cookie HTTP header to set cookies.
Here, some properties for setting cookies are optional, such as Expires, Domain and Path. It is worth noting that cookies are set before sending the line "Content-type:text/html\r\n\r\n.
Compile the above program to generate setcookies .cgi and try to set cookies using the link below. It will set four cookies on your computer:
/cgi-bin/setcookies.cgi
Get Cookies
Retrieving all set cookies is very simple. Cookies are stored in the CGI environment variable HTTP_COOKIE, and they have the following form:
key1=value1;key2=value2;key3=value3....
The following example demonstrates how to obtain cookies. #Now, compile the above program to generate getcookies.cgi and try to get all the cookies available on your computer using the following link:
/cgi-bin/getcookies.cgi
this A list will be generated showing the four cookies set in the previous section as well as all other cookies on your computer:
#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"; cout << "<head>\n"; cout << "<title>CGI 中的 Cookies</title>\n"; cout << "</head>\n"; cout << "<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"; cout << "<br/>\n"; cout << "</body>\n"; cout << "</html>\n"; return 0; }
File Upload Example
In order to upload a file, the HTML form must Setting the enctype attribute to
multipart/form-data will create a "Browse" button with the input tag UserID XYZ
Password XYZ123
Domain www.w3cschool.cc
Path /perl
The result of this code is the following form:
The above example has intentionally disabled saving uploaded files on our server. You can try the above code on your own server. The following is the code. Script
cpp_uploadfile.cpp for handling file uploads: <html>
<body>
<form enctype="multipart/form-data"
action="/cgi-bin/cpp_uploadfile.cgi"
method="post">
<p>文件:<input type="file" name="userfile" /></p>
<p><input type="submit" value="上传" /></p>
</form>
</body>
</html>
The above example writes content to the
stream, but you can open a file stream and Save the uploaded file contents in a file in the target location.