Software Carpentry logo

Web Application Programming

April 24, 2010: We are pleased to announce that Version 4 of this course is now under development. For updates and an early peek at the content, please check out the Software Carpentry blog at http://www.software-carpentry.org/blog/.

1) Introduction

2) You Can Skip This Lecture If...

3) The Pluggable Web

4) The CGI Protocol

5) From Server To CGI

6) From CGI To Server

7) MIME Types

8) Hello, CGI

#!/usr/bin/env python

# Headers and an extra blank line
print 'Content-type: text/html'
print

# Body
print '<html><body><p>Hello, CGI!</p></body></html>'

9) Invoking a CGI

10) Generating Dynamic Content

#!/usr/bin/env python

import os, cgi

# Headers and an extra blank line
print 'Content-type: text/html'
print

# Body
print '<html><body>'
keys = os.environ.keys()
keys.sort()
for k in keys:
    print '<p>%s: %s</p>' % (cgi.escape(k), cgi.escape(os.environ[k]))
print '</body></html>'
Environment Variable Output

Figure 24.3: Environment Variable Output

11) Forms

12) Creating Forms

13) A Simple Form

<html>
<body>
<form action="http://www.third-bit.com/cgi-bin/simple_form.py" method="POST">
  <p>Sequence: <input name="sequence" type="text" value="GATTACA"/>
     Search type:
     <select name="search_type">
       <option>Exact match</option>
       <option selected="selected">Similarity match</option>
       <option>Sub-match</option>
     </select>
  </p>
  <p>Programs:
    <input checked="checked" name="program" type="checkbox" value="FROG-11">
      FROG (version 1.1)
    </input>
    <input name="program" type="checkbox" value="FROG-beta">
      FROG (2.0 beta)
    </input>
    <input checked="checked" name="program" type="checkbox" value="Bayes-Hart">
      Bayes-Hart
    </input>
  </p>
  <p>
    <input type="submit"/>
    <input type="reset"/>
  </p>
</form>
</body>
</html>
A Simple Form

Figure 24.4: A Simple Form

14) Parameter Names

15) Handling Forms

16) Form Handling Example

#!/usr/bin/env python
import cgi

print 'Content-type: text/html'
print
print '<html><body>'
form = cgi.FieldStorage()
for key in form.keys():
    value = form.getvalue(key)
    if isinstance(value, list):
        value = '[' + ', '.join(value) + ']'
    print '<p>%s: %s</p>' % (cgi.escape(key), cgi.escape(value))
print '</body></html>'
URL Value of a Value of b
http://www.third-bit.com/swc/show_params.py?a=0 "0" None
http://www.third-bit.com/swc/show_params.py?a=0&b=hello "0" "hello"
http://www.third-bit.com/swc/show_params.py?a=0&b=hello&a=22 [0, 22] "hello"

Table 24.3: Example Parameter Values

17) Development Tips

18) Maintaining State

19) Maintaining State in Files

Hi, is anyone reading this site?
I was wondering the same thing.
I wasn't sure if we were supposed to post here.
Good point.  Is there way to delete messages?
# Get existing messages.
infile = open('messages.txt', 'r')
lines = [x.rstrip() for x in infile.readlines()]
infile.close()

# Add more data?
form = cgi.FieldStorage()
if form.has_key('newmessage'):
    lines.append(form.getfirst('newmessage'))
    outfile = open('messages.txt', 'w')
    for line in lines:
        print >> outfile, line
    outfile.close()

20) HTML Generation

# Display.
print 'Content-Type: text/html'
print
print '<html><body>'
for line in lines:
    print '<p>' + line + '</p>'
print '''
<form action="http://www.third-bit.com/swc/message_form.py" method="post">
  <p>Your message:
     <input name="newmessage" type="text"/>
  </p>
  <p>
    <input type="submit"/>
    <input type="reset"/>
  </p>
</form>
'''
print '</body></html>'

21) HTML Templating

22) What About Concurrency?

23) File Locking

24) Implementing Locking

# Get existing messages.
msgfile = open('messages.txt', 'r+')
fcntl.flock(msgfile.fileno(), fcntl.LOCK_EX)
lines = [x.rstrip() for x in msgfile.readlines()]

# Add more data?
form = cgi.FieldStorage()
if form.has_key('newmessage'):
    lines.append(form.getfirst('newmessage'))
    msgfile.seek(0)
    for line in lines:
        print >> msgfile, line

# Unlock and close.
fcntl.flock(msgfile.fileno(), fcntl.LOCK_UN)
msgfile.close()

25) Who Are You?

26) Cookies

27) Creating Cookies

28) Cookie Example

# Get old count.
count = 0
if os.environ.has_key('HTTP_COOKIE'):
    cookie = Cookie.SimpleCookie()
    cookie.load(os.environ['HTTP_COOKIE'])
    if cookie.has_key('count'):
        count = int(cookie['count'].value)

# Create new count.
count += 1
cookie = Cookie.SimpleCookie()
cookie['count'] = count

# Display.
print 'Content-Type: text/html'
print cookie
print
print '<html><body>'
print '<p>Visits: %d</p>' % count
print '</body></html>'

29) Cookie Tips

30) Summmary