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. Consequently, CGI applications can be written in nearly all programming languages.
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.
A CGI-compatible web server, such as thttpd, Hiawatha, or lighttpd, is required to connect Fortran programs to the World Wide Web. On FreeBSD, we can install thttpd simply as a package:
# pkg install www/thttpd
- Fig. 1: The output of the CGI application written in Fortran
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 :: sz, rc
! 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"><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=rc) sz
! Note: content is not HTML encoded!
if (rc == 0 .and. sz > 0) then
allocate (character(len=sz) :: post_data)
read (*, '(a)', iostat=rc) post_data
print *, '<pre><code>' // post_data // '</code></pre>'
end if
print '(a)', FOOTER
end program webapp
Compile the source code to executable webapp
:
$ gfortran12 -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
Server Configuration
On FreeBSD, the thttpd 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
Server Software
- Althttpd: CGI-compatible web server of the SQLite project
- Hiawatha: Advanced web server that also runs CGI applications
- lighttpd: Fast web server, includes CGI module
- thttpd: Small HTTP server with CGI support, by ACME Labs
- slowcgi: FastCGI spawner that runs CGI applications
References
- S. Gundavaram: CGI Programming on the World Wide Web, 1996
- N. Kew: CGI Programming FAQ, 2000
< cURL | [Index] | FastCGI > |