You may have heard of CGI, or the Common Gateway Interface, which is simply a standard way for a web server to run a program that dynamically generates a web page. In reality all that is happening is that there is a program (running in whatever language the developer decided to use) that is generating HTML on the fly and the output of that program is returned to the browser.
There are a few common methods of sending a request to a web server. In this class we focus on GET and POST. With GET, all of the form data is encoded within the URL and sent as part of the HTTP headers, and with POST the same data is provided in the body of the HTTP request, as you may remember from the previous class. For each HTTP request received, the web server sets multiple environment variables and the stdin with different pieces of information it receives in the request. For the data sent using thr GET method, an environment variable called "QUERY_STRING" is set on the server with the data received.
When you use a web server that supports CGI, like the Apache2 server we use with our classes, this data is provided to the scripts via environment variables that the program can read while it is executing. This means that any programming language can be used.
Lets take a look at a C++ program that would perform these actions. Note that this was pulled and modified from https://www.tutorialspoint.com/cplusplus/cpp_web_programming.htm :
#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()
{
// Set the return header
cout << "Content-type:text/html\n\n";
// Output the text (our HTML)
cout << "<!DOCTYPE html>\n"
cout << "<html lang = \"en\">\n";
cout << "<head>\n";
cout << "<title>CGI Environment Variables</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<table>";
for ( int i = 0; i < 24; i++ ) {
cout << "<tr><td>" << ENV[ i ] << "</td><td>";
// attempt to retrieve value of environment variable
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";
cout << "</html>\n";
return 0;
}
g++ example.cpp -o test.cgi
Take the compiled file and move/rename it to
~/public_html/IT350/CGIIntro/test.cgi - we have to
rename it to a .cgi file so the web server knows that it should
try to execute it vice simply returning the file to the user.
cd ~/public_html/IT350/CGIIntro
./test.cgi
http://midn.cs.usna.edu/~mXXXXXX/IT350/CGIIntro/test.cgi
What do you see when you run it from the command line, and when you view the file on the website? Do "View page source" in the browser to see the source received by the browser as well.
Well this means that instead of having static HTML files that never change, we can write programs that will produce HTML on the fly. This is how we will make dynamic websites that are interactive for our users, or that can provide up to date information. The data sent by the user can be retrieved from the QUERY_STRING environment variable or stdin, parsed, and used to dynamically generate personalized webpages.
A few notes:
curl http://midn.cs.usna.edu/~mXXXXXX/IT350/CGIIntro/ex1.cgi?maxNumber=5
To save the results, redirect stdout from curl to a file:
curl http://midn.cs.usna.edu/~mXXXXXX/IT350/CGIIntro/ex1.cgi?maxNumber=5 > results.html
cd ~/public_html/IT350
~/bin/submit -c=IT350 -p=CGIIntro CGIIntro
This assumes that the submit script is located in ~/bin/ and is executable.