Setting up Python CGI

Setting up python scripts for use in support of web pages can be tricky in view of security concerns. Normally, a common gateway interface (CGI) script would simply be a program in a cgi-bin directory, executed directly, as in

http://arcib.dowling.edu/~bernsteh/cgi-bin/pystat.py

However, for security reasons, the direct execution path via the web server is normally disabled. Instead, the python script has to be executed running as an ordinary user, rather than from a system account as

http://arcib.dowling.edu/cgi-bin/cgiwrap/bernsteh/pystat.py

The code in pystat.py, could, for example, be a variant of the code at

http://code.activestate.com/recipes/52220-the-simplest-cgi-program/:

#!/usr/bin/python2.5
print "Content-type: text/html"
print
print "<html>"
print "<head>"
print "<title>pystat.py</title>"
print "</head>"
print "<body>"
print "<pre>"
import os, sys
from cgi import escape
print "<strong>Python %s</strong>" % sys.version
keys = os.environ.keys()
keys.sort()
for k in keys:
    print "%s\t%s" % (escape(k), escape(os.environ[k]))
print "</pre>"
print "</body>"
print "</html>"

If this is stored as pystat.py in the public_html/cgi-bin/ directory of the user bernsteh on arcib.dowling.edu and made executable by

chmod 755 pystat.py

then going to the url

http://arcib.dowling.edu/cgi-bin/cgiwrap/bernsteh/pystat.py?arg1=1&arg2=2

should produce the output

Python 2.5.1 (r251:54863, May  4 2007, 16:52:23) 
[GCC 4.1.2]
DOCUMENT_ROOT	/var/www/html/arcib
GATEWAY_INTERFACE	CGI/1.1
HTTP_ACCEPT	text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_CHARSET	ISO-8859-1,utf-8;q=0.7,*;q=0.7
HTTP_ACCEPT_ENCODING	gzip,deflate
HTTP_ACCEPT_LANGUAGE	en-us,en;q=0.5
HTTP_CACHE_CONTROL	max-age=0
HTTP_CONNECTION	keep-alive
HTTP_COOKIE	__utma=257279262.3665434704854877700.1236790017.1287598061.1287602078.155; __utmz=257279262.1282495313.110.10.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=dowling%20college
HTTP_HOST	arcib.dowling.edu
HTTP_KEEP_ALIVE	115
HTTP_USER_AGENT	Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.11) Gecko/20101012 Firefox/3.6.11
PATH	/bin:/usr/bin:/sbin:/usr/sbin
PATH_TRANSLATED	/var/www/html/arcib/bernsteh/pystat.py
QUERY_STRING	arg1=1&arg2=2
REMOTE_ADDR	149.72.1.251
REMOTE_PORT	49605
REQUEST_METHOD	GET
REQUEST_URI	/cgi-bin/cgiwrap/bernsteh/pystat.py?arg1=1&arg2=2
SCRIPT_FILENAME	/home/faculty/bernsteh/public_html/cgi-bin/pystat.py
SCRIPT_NAME	/cgi-bin/cgiwrap/bernsteh/pystat.py
SERVER_ADDR	149.72.27.28
SERVER_ADMIN	terahz@geodar.com
SERVER_NAME	arcib.dowling.edu
SERVER_PORT	80
SERVER_PROTOCOL	HTTP/1.1
SERVER_SIGNATURE	
Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.8e DAV/2 PHP/5.2.3 Server at arcib.dowling.edu Port 80
SERVER_SOFTWARE Apache/2.2.4 (Unix) mod_ssl/2.2.4 OpenSSL/0.9.8e DAV/2 PHP/5.2.3 UNIQUE_ID UQTpQpVIGxwAAEirX7MAAAAJ

Note that the arguments passed as "arg1=1&arg2=2" are now the value for the key "QUERY_STRING" in the dictionary os.environ, i.e. the value of os.environ["QUERY_STRING"]