A Hypothetical Scenario
You run a personal website from the
public_www subdirectory of a shell account provided to you by your local dialup internet service provider.
Having a shell account affords you the ability to serve static HTML files, but during that era, if you wanted to generate dynamic content, like a hit counter that records website visits or a guest book (the comments section of websites in worlds past), things were not so simple.
In this article, we will take a look at CGI scripts, a technology of the early web that enabled software tinkerers to build simple (but useful) dynamic web apps.
CGI stands for “Common Gateway Interface”. During the 90s, CGI scripts provided the most viable option for individuals wishing to host dynamically rendered server-side content. If you’ve never seen one in action before, take a look at this example script I wrote. It dynamically displays the current time and user agent to the visitor. The example script is written in Bash, although historically, most CGI scripts were written in Perl (examples).
The source code to my example script is below. If you’ve never written an HTTP request by hand, check out my article about HTTP request anatomy:
#!/usr/bin/bash echo "Content-type: text/html" echo "" echo '<html>' echo ' <body>' echo ' <p>The time is: ' # Prints current date/time to STDOUT: date echo ' </p>' echo ' <p>Your HTTP user agent is:' # A CGI-enabled server will set this ENV var at runtime: echo $HTTP_USER_AGENT echo ' </p>' echo ' </body>' echo '</html>' exit 0
As you can see in the example above, all writes to STDOUT were translated to an HTTP response. Some information (such as
$QUERY_STRING) are provided by the server at runtime. By providing a simple means of input (ENV) and output (STDOUT), CGI scripts were a very powerful tool for early web developers, particularly hobbyists and small scale developers. All you needed was a programming language and a CGI-enabled web server.
CGI scripts were often placed in a
cgi-bin directory. When the server received a request to a particular CGI script, it would execute the script rather than serve its content.
The practice was eventually formalized in RFC 3875. Many of the RFC’s collaborators were themselves authors of HTTP servers.
Like the Year 1996, All Things Come to Pass
CGI scripting was undoubtedly useful and continues to be useful for small scale web applications, such as developer utilities, simple form data collection and local intranet tools.
CGI scripts were not the right tool for every job and their obsolescence is the result of better alternatives. The “one process per request” model offered by CGI scripting suffered from a number of problems, most notably an I/O performance loss. A CGI application that uses a database must open a connection to the database once per request, which incurs connection overhead. Furthermore, a CGI script with 100 users will inevitably create 100 OS processes (possibly more if it is executing sub-commands).
Another cause of CGI scripting’s demise was an inability to handle the complexity of large scale applications. Such problems were better handled by web development frameworks which arrived shortly after the CGI script.
Additionally, since the server was directly executing the script, security issues could easily creep in (the script shares the permissions of the HTTP server).
The inefficiencies of CGI scripts eventually led to the creation of more robust solutions such as FCGI, SCGI, numerous web frameworks and, more recently, “Function as a Service” platforms, which addressed many of the concerns listed while also adding additional features.