CGI
Common Gateway Interface (CGI) is an API that allows programs to respond to HTTP client requests through a web server, as specified in RFC 3875. The protocol was introduced in the 1990s to connect databases and applications to the World Wide Web:
The Common Gateway Interface (CGI) is a standard for interfacing external applications with information servers, such as HTTP or Web servers. A plain HTML document that the Web daemon retrieves is static, which means it exists in a constant state: a text file that doesn’t change. A CGI program, on the other hand, is executed in real-time, so that it can output dynamic information.
– The Common Gateway Interface: Introduction
The web server forwards incoming requests to the designated CGI script or program, and returns the given response to the client. The inter-communication between web server and CGI program is based on standard input/output. Requests are passed through environment variables within the CGI application context (table 1). Consequently, CGI applications can be written in nearly all programming languages.
-
Variable Description AUTH_TYPE
Authentication method used to validate a visitor. CONTENT_LENGTH
Length of the query data (in bytes or the number of characters) passed to the CGI program through standard input. CONTENT_TYPE
Media type of the query data, such as text/html
.GATEWAY_INTERFACE
Revision of the Common Gateway Interface that the server uses. DOCUMENT_ROOT
Root directory of the server. HTTP_ACCEPT
List of the media types that the client can accept. HTTP_COOKIE
Visitor’s cookie, if one is set. HTTP_REFERER
URL of the page that called the CGI program. HTTP_USER_AGENT
Browser type of the visitor. PATH_INFO
Extra path information passed to a CGI program. PATH_TRANSLATED
Translated version of the path given by PATH_INFO
.QUERY_STRING
GET query string. REMOTE_ADDR
IP address of the visitor. REMOTE_HOST
Hostname of the visitor (if the server supports reverse name-lookups, otherwise this is the IP address again). REMOTE_IDENT
Visitor making the request. REMOTE_USER
Visitor’s user name (if authenticated). REQUEST_METHOD
Method with which the information request was issued (GET, POST, …). REQUEST_URI
Interpreted path name of the requested document or CGI (relative to the document root). SCRIPT_NAME
Interpreted path name of the current CGI program (relative to the document root). SERVER_NAME
FQDN or IP address of the server. SERVER_PORT
Port number the server is listening on. SERVER_PROTOCOL
Name and revision number of the server protocol. SERVER_SOFTWARE
Name and version of the server software. - Table 2: Common CGI environment variables
Client data is sent using the HTTP methods GET and POST:
- GET
- The data is given as key-value pairs in environment variable
QUERY_STRING
. Pairs are separated by an ampersand (&
), white space characters are encoded as+
or%20
. - POST
- Any data sent by POST can simply be read from standard input.
The size is given in environment variable
CONTENT_LENGTH
, the MIME type inCONTENT_TYPE
.
CGI has the drawback of starting a new process for each HTTP request, and, therefore, producing some overhead related to process management and memory consumption, especially, if the CGI program is written in a scripting language. In the mid-1990s, the FastCGI protocol was released to address these shortcomings by creating persistent processes that handle multiple requests.
-
Web Server Licence CGI FastCGI SCGI Althttpd PD ✓ ✓ Apache HTTP Server Apache ✓ ✓ Boa GPL ✓ Cherokee GPL ✓ ✓ ✓ Hiawatha GPL ✓ ✓ lighttpd BSD ✓ ✓ ✓ NaviServer MPL ✓ nginx BSD ✓ ✓ thttpd BSD ✓ - Table 2: Free and open-source web server software
A CGI-compatible web server is required to connect Fortran programs to the World Wide Web (table 2).
Web Application
The example CGI application does not depend on any third-party libraries,
only the intrinsic subroutine get_environment_variable()
(Fortran
2003) is called to read some
CGI environment variables.
! webapp.f90
program webapp
implicit none
character(len=*), parameter :: CR_LF = achar(13) // achar(10)
character(len=*), parameter :: CONTENT_TYPE = 'text/html'
character(len=*), parameter :: HEADER = '<!doctype html>' // &
'<html lang="en">' // &
'<head><meta charset="utf-8">' // &
'<title>Fortran + CGI</title></head>' // &
'<body bgcolor="silver">'
character(len=*), parameter :: FOOTER = '</body></html>'
character(len=72) :: env
character(len=:), allocatable :: post_data
integer :: stat, sz
! Output HTTP header.
print '(a)', 'Content-Type: ' // CONTENT_TYPE // CR_LF // CR_LF
! Output HTML header.
print '(a)', HEADER
print '(a)', '<h1>Hello, from Fortran!</h1>'
! Read and output CGI environment variables.
print '(a)', '<table border="1">'
print '(a)', '<tr><th>Key</th><th>Value</th></tr>'
call get_environment_variable('SERVER_SOFTWARE', env)
print '(a)', '<tr><td>SERVER_SOFTWARE</td><td>' // trim(env) // '</td></tr>'
call get_environment_variable('GATEWAY_INTERFACE', env)
print '(a)', '<tr><td>GATEWAY_INTERFACE</td><td>' // trim(env) // '</td></tr>'
call get_environment_variable('QUERY_STRING', env)
print '(a)', '<tr><td>QUERY_STRING</td><td>' // trim(env) // '</td></tr>'
print '(a)', '</table>'
! Read and output POST data.
call get_environment_variable('CONTENT_LENGTH', env)
read (env, *, iostat=stat) sz
! Note: To prevent XSS attacks, all user input should be properly escaped!
if (stat == 0 .and. sz > 0) then
allocate (character(len=sz) :: post_data)
read (*, '(a)', iostat=stat) post_data
print *, '<pre><code>' // post_data // '</code></pre>'
end if
print '(a)', FOOTER
end program webapp
Compile the source code to executable webapp
:
$ gfortran13 -o webapp webapp.f90
Then, copy the binary to the cgi-bin/
directory of the web
server, in this case, /var/www/cgi-bin/
, and make the file
executable:
# cp webapp /var/www/cgi-bin/
# chmod u+x /var/www/cgi-bin/webapp
- Fig. 1: The output of the CGI application written in Fortran
Server Configuration
We can use any CGI-compatible web server to run the web application, such as thttpd. On FreeBSD, simply install the server as a package:
# pkg install www/thttpd
The web server is configured through file
/usr/local/etc/thttpd.conf
. The served directory is set to
/var/www
but can be anywhere on the file system. The CGI path will
resolve to /var/www/cgi-bin/
:
dir=/var/www
cgipat=/cgi-bin/*
logfile=/var/log/thttpd.log
pidfile=/var/run/thttpd.pid
port=80
user=www
nochroot
Start the web server as a daemon:
# service thttpd onestart
Starting thttpd.
Access http://127.0.0.1/cgi-bin/webapp
in a web browser to show
the output of the CGI application (fig. 1). We can run cURL to pass data via
POST method:
$ curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d "param1=value" http://127.0.0.1/cgi-bin/webapp
Fortran Libraries
- FABS: Web framework based on Fortran, Apache, BSD, and SQLite
FastCGI Wrappers
- fcgiwrap: Simple FastCGI wrapper for CGI scripts
- slowcgi: FastCGI spawner that runs CGI applications
References
- S. Gundavaram: CGI Programming on the World Wide Web, 1996
- N. Kew: CGI Programming FAQ, 2000
< HTTP Client | [Index] | FastCGI > |